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

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

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

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

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

3 ответа

Решение

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

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

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

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

Когда вы дважды щелкаете внутри текстовой области, он выбирает основное слово.

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