Pergunta

I have a multi-line text box that displays some values based on data it gets given, (Generally one value per line).

(For the purpose of having a tool tip popup with some 'alternative' data) I would like to get the word (or at the very least the line) that the mouse is hovering over so I can then find what alternative to display.

I have a few ideas of how to do this with calculations based on the text box and font sizes but I do not what to go down this road as the sizes and fonts may change frequently.

So... Is there any way of using the mouses position to grab specific text box text?

Foi útil?

Solução

Here's an alternate solution. Add this MouseMove event to your TextBox:

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);
}

Outras dicas

Use the GetCharIndexFromPosition method to map the mouse's position to an index in the whole Text. From that position, progress left and right till you have the whole word.

To get the mouse position, use the MouseHover event, so that you get it just when it's still and not every time (that would make things slow).

My solution uses a trick to achieve what you want.

When you double click inside a text area, it select the underlying word.

So using a RichTextBox (TextBox does flash on mouse events) on your form you can simulate double click when the middle mouse button is clicked (something like Babylon dictionary). If you want you can use MouseHover instead of MouseDown, too. It works.

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();
            }
        }
    }
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top