Как получить определенное текстовое значение из текстового поля на основе позиции мыши

У меня есть многострочное текстовое поле, которое отображает некоторые значения на основе данных, которые он получает, (обычно одно значение для каждой строки).

(Чтобы иметь всплывающее подсказку с некоторыми "альтернативными" данными), я хотел бы получить слово (или, по крайней мере, строку), которое мышь нависает, поэтому я могу найти, какую альтернативу дисплей.

У меня есть несколько идей о том, как это сделать с вычислениями, основанными на текстовом поле и размерах шрифтов, но я не хочу, чтобы идти по этой дороге, так как размеры и шрифты могут часто меняться.

Итак... Есть ли способ использовать положение мыши для захвата текста текстового поля?

Ответ 1

Здесь альтернативное решение. Добавьте это событие MouseMove в 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);
}

Ответ 2

Используйте метод GetCharIndexFromPosition, чтобы отобразить позицию мыши в индекс во всем тексте. С этой позиции продвигайтесь влево и вправо, пока не получите полное слово.

Чтобы получить положение мыши, используйте событие MouseHover, чтобы вы его получили, когда он все еще и не каждый раз (это замедлит работу).

Ответ 3

Мое решение использует трюк для достижения того, чего вы хотите.

При двойном щелчке внутри текстовой области выбирается основное слово.

Таким образом, используя 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 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();
            }
        }
    }