[英]Move Caret to Mouse Position in WPF Text Box
我有一个子类文本框,只有当用户有意点击它时才会获得键盘焦点(插入符号)(它是复杂控件的一部分,用户可能并不总是想要这种行为)。
因此,我必须在代码中(使用 Keyboard.Focus)为文本框提供这个焦点,所以我不能依赖现有的行为来做到这一点。
问题是当用户点击(并且我调用 Keyboard.Focus)时,插入符号位置没有设置。 这不直观,而且有点令人沮丧,需要用户进行第二次单击操作(一旦获得键盘焦点)以将插入符号放置在他们想要的正确位置。
我会使用 GetCharacterIndexFromPoint,但它会给你错误的索引! 如果你的鼠标超出了最后一个字符,它会在点击时将插入符号放在它之前,在我看来,这比没有任何行为更令人恼火。
为此,我如何获取鼠标位置并从中导出合适的插入符号位置,以模仿控件的开箱即用行为(插入符号跳转到最接近鼠标的有效位置)的方式?
我以前研究过这个,结果是空白。
我找到了答案。
它的解决方案2 在这里由用户EriBeh,复制如下:
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);
然而,该解决方案并不完全正确,因为它没有考虑任何填充或文本对齐。 仅仅计算文本的宽度是不够的,还必须考虑文本在控件中的位置,并据此导出其最右边的点(相对于控件),然后可以测试鼠标是否更靠右派生值。
因此,我对此进行了调整(我的文本将始终在控件中居中):
SizeF size;
using (var graphics = Graphics.FromImage(new Bitmap(1, 1)))
{
size = graphics.MeasureString(Text, new Font(FontFamily.ToString(), Convert.ToSingle(FontSize), System.Drawing.FontStyle.Regular, GraphicsUnit.Pixel));
}
var mousepos = Mouse.GetPosition(this);
var textXLocationAtRightmostEdge = (ActualWidth / 2) + (size.Width / 2);
CaretIndex = mousepos.X >= textXLocationAtRightmostEdge ? Text.Length : GetCharacterIndexFromPoint(mousepos, 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 });
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.