C# 在WPF文本框中将插入符号移动到鼠标位置
我有一个子类文本框,只有当用户有意点击它时,它才会获得键盘焦点(插入符号)(这是复杂控件的一部分,用户可能并不总是想要这样的行为) 因此,我必须在代码中给文本框这个焦点(使用Keyboard.focus),所以我不能依赖现有的行为来完成它 问题是,当用户单击时(我调用Keyboard.Focus),插入符号的位置没有设置。这并不直观,也有点令人沮丧,需要用户进行第二次单击操作(一旦获得键盘焦点)以将插入符号放置在他们想要的正确位置 我会使用GetCharacterIndexFromPoint,但它给了你错误的索引!如果你的鼠标超过了最后一个字符,它会在点击时把插入符号放在它的前面,在我看来,这可能比没有任何行为更令人恼火 为此,我如何获得鼠标位置并从中导出合适的插入符号位置,以模仿控件的开箱即用行为(插入符号跳到离鼠标最近的有效位置) 我以前对此进行过研究,结果一无所获 我找到了答案 这是用户EriBeh提供的解决方案2,复制如下:C# 在WPF文本框中将插入符号移动到鼠标位置,c#,wpf,mouseevent,C#,Wpf,Mouseevent,我有一个子类文本框,只有当用户有意点击它时,它才会获得键盘焦点(插入符号)(这是复杂控件的一部分,用户可能并不总是想要这样的行为) 因此,我必须在代码中给文本框这个焦点(使用Keyboard.focus),所以我不能依赖现有的行为来完成它 问题是,当用户单击时(我调用Keyboard.Focus),插入符号的位置没有设置。这并不直观,也有点令人沮丧,需要用户进行第二次单击操作(一旦获得键盘焦点)以将插入符号放置在他们想要的正确位置 我会使用GetCharacterIndexFromPoint,但
SizeF size;
using (Graphics graphics = Grapics.FromImage(new Bitmap(1, 1)))
{
size = graphics.MeasureString(CustomTextBox.Text, new Font(CustomTextBox.FontFamily.ToString(), Convert.ToSingle(CustomTextBox.FontSize), System.Drawing.FontStyle.Regular, GraphicsUnit.Pixel));
}
if (mousePoint.X >= size.Width) return CustomPasswordBox.Password.Length;
else CustomTextBox.GetCharacterIndexFromPoint(mousePoint, true);
然而,解决方案并不完全正确,因为它不考虑任何填充或文本对齐。仅仅计算文本的宽度是不够的,还必须考虑文本位于控件中的位置,并相应地导出其最右点(相对于控件),然后可以测试鼠标相对于该派生值是否正确。
因此,我对其进行了调整(我的文本将始终以控件为中心):
非常感谢优秀的解决方案。我遇到了类似的问题,因为我的文本框也可以包装,所以不能使用文本或文本框的宽度。所以我想出了(而且还没有发现任何问题)这个解决方案
MouseDownStartPosition = e.GetPosition(textBox);
//check if user clicked some exact character
var characterIndexFalse = textBox.GetCharacterIndexFromPoint(MouseDownStartPosition, false);
//get nearest character to mouse
var characterIndex = textBox.GetCharacterIndexFromPoint(MouseDownStartPosition, true);
//GetCharacterIndexFromPoint often returns last but one character position when clicked right after textbox
//so check if characterIndexFalse is -1 (text not clicked) and if nearest character is last but one, assume that
//user clicked behind string
if ((characterIndexFalse == -1) && (characterIndex + 1 == textBox.Text.Length)) {
characterIndex++;
}
简要说明:
GetCharacterIndexFromPoint(true)返回与字符串中最后一个字符有问题的最近字符,并选择倒数第二个字符
GetCharacterIndexFromPoint(false)返回完全单击的字符,如果未单击字符,则返回-1
所以为了解决这个问题,我检查是否没有单击任何精确的字符,最近的字符是最后一个,但我知道插入符号需要放在最后一个字符之后。我可以在这里添加我的2美分吗 为什么不让WPF系统自己处理呢
// Get the protected OnMouseDown method via reflection.
var textBoxBaseType = typeof(TextBoxBase);
var onMouseDownMethod = textBoxBaseType.GetMethod("OnMouseDown", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
System.Diagnostics.Debug.Assert(onMouseDownMethod != null);
Point mousePoint = Mouse.GetPosition(txtBox);
var mea = new MouseButtonEventArgs(Mouse.PrimaryDevice, Environment.TickCount, MouseButton.Left);
mea.RoutedEvent = e.RoutedEvent; // Where e = the EventArgs parameter passed on to this method
txtBox.SelectionLength = 0;
onMouseDownMethod.Invoke(txtBox, new[] { mea });
请向我们展示如何使用GetCharacterIndexFromPoint.MyTextBox.CaretIndex=GetCharacterIndexFromPoint(Mouse.GetPosition(this),true);
// Get the protected OnMouseDown method via reflection.
var textBoxBaseType = typeof(TextBoxBase);
var onMouseDownMethod = textBoxBaseType.GetMethod("OnMouseDown", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
System.Diagnostics.Debug.Assert(onMouseDownMethod != null);
Point mousePoint = Mouse.GetPosition(txtBox);
var mea = new MouseButtonEventArgs(Mouse.PrimaryDevice, Environment.TickCount, MouseButton.Left);
mea.RoutedEvent = e.RoutedEvent; // Where e = the EventArgs parameter passed on to this method
txtBox.SelectionLength = 0;
onMouseDownMethod.Invoke(txtBox, new[] { mea });