繁体   English   中英

将插入符号移动到 WPF 文本框中的鼠标位置

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM