如何根据鼠标位置从文本框中获取特定的文本值

11

我有一个多行文本框,根据给定的数据显示一些值(通常每行一个值)。

(为了使用工具提示弹出窗口显示一些“替代”数据),我想获取鼠标悬停的单词(或至少是行),以便我可以找到要显示的替代内容。

我有一些关于如何通过文本框和字体大小进行计算的想法,但我不想走这条路,因为大小和字体可能经常更改。

那么...有没有办法利用鼠标位置来获取特定文本框的文本?

3个回答

9
这里有一个备选方案。将以下MouseMove事件添加到您的文本框中:
private void txtHoverWord_MouseMove(object sender, MouseEventArgs e)
{
    if (!(sender is TextBox)) return;
    var targetTextBox = sender as TextBox;
    if(targetTextBox.TextLength < 1) return;

    var currentTextIndex = targetTextBox.GetCharIndexFromPosition(e.Location);

    var wordRegex = new Regex(@"(\w+)");
    var words = wordRegex.Matches(targetTextBox.Text);
    if(words.Count < 1) return;

    var currentWord = string.Empty;
    for (var i = words.Count - 1; i >= 0; i--)
    {
        if (words[i].Index <= currentTextIndex)
        {
            currentWord = words[i].Value;
            break;
        }
    }
    if(currentWord == string.Empty) return;
    toolTip.SetToolTip(targetTextBox, currentWord);
}

谢谢,这个方案非常有效!我也喜欢使用的正则表达式来去除空格! :) - Jammerz858
很高兴你喜欢它。请注意,它并不仅仅是删除空格。它只保留正则表达式认为是单词的内容,因此标点符号和其他任何非单词的内容都将被删除。 - Michael Sallmen

4
使用GetCharIndexFromPosition方法将鼠标位置映射到整个文本中的索引。从该位置向左和向右移动,直到获得整个单词。
要获取鼠标位置,请使用MouseHover事件,以便在其静止时获取位置,而不是每次都获取(这会使事情变慢)。

谢谢。我采纳了您的建议,使用鼠标悬停事件而不是mousemove事件,这使得效果更加用户友好。感谢您的帮助。 - Jammerz858

2
我的解决方案使用了一个技巧来实现您想要的功能。
当您在文本区域内双击时,它会选择下面的单词。
因此,在您的表单上使用 RichTextBox(TextBox 在鼠标事件上会闪烁),您可以模拟在单击中间鼠标按钮时进行双击(类似 Babylon 字典)。如果您愿意,也可以使用 MouseHover 而不是 MouseDown。它可以工作。
public partial class Form3 : Form
    {
        System.Windows.Forms.Timer timer = new System.Windows.Forms.Timer();

        public Form3()
        {
            InitializeComponent();
            timer.Interval = 50;
            timer.Tick += timer_Tick;
        }

        void timer_Tick(object sender, EventArgs e)
        {
            timer.Stop();
            MessageBox.Show(richTextBox1.SelectedText);

            // do more stuff here, e.g display your tooltip for the selected word or anything else 

            richTextBox1.SelectionLength = 0; // remove the highlighted color of selection
        }

        [DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
        public static extern void mouse_event(uint dwFlags, uint dx, uint dy, uint cButtons, uint dwExtraInfo);

        private const uint MOUSEEVENTF_LEFTDOWN = 0x02;
        private const uint MOUSEEVENTF_LEFTUP = 0x04;
        private const uint MOUSEEVENTF_RIGHTDOWN = 0x08;
        private const uint MOUSEEVENTF_RIGHTUP = 0x10;

        public void DoMouseDoubleClick()
        {
            //Call the imported function with the cursor's current position
            uint X = (uint)Cursor.Position.X;
            uint Y = (uint)Cursor.Position.Y;

            mouse_event(MOUSEEVENTF_LEFTDOWN, X, Y, 0, 0);
            mouse_event(MOUSEEVENTF_LEFTUP, X, Y, 0, 0);
            mouse_event(MOUSEEVENTF_LEFTDOWN, X, Y, 0, 0);
            mouse_event(MOUSEEVENTF_LEFTUP, X, Y, 0, 0);

            timer.Start(); // some delay is required so that mouse event reach to RichTextBox and the word get selected
        }

        private void richTextBox1_MouseDown(object sender, MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Middle)
            {
                DoMouseDoubleClick();
            }
        }
    }

相当不错的解决方案... 但对于需求来说有点太复杂了。无论如何,感谢您的帮助。 - Jammerz858

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接