Как я могу определить, находится ли мышь над окном верхнего уровня? - PullRequest
5 голосов
/ 10 октября 2010

Как я могу эффективно определить, находится ли мышь над окном верхнего уровня?

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

Я пишу на C # с использованием Windows Forms, но я не против использоватьp / invoke для вызова Win32.

Ответы [ 2 ]

4 голосов
/ 10 октября 2010

Вы можете использовать функцию WinAPI WindowFromPoint. Его подпись на C #:

[DllImport("user32.dll")]
static extern IntPtr WindowFromPoint(POINT Point);

Обратите внимание, что POINT здесь не то же самое, что System.Drawing.Point, но PInvoke предоставляет объявление для POINT, которое включает в себя неявное преобразование между двумя .

Если вы еще не знаете положение курсора мыши, GetCursorPos находит его:

[DllImport("user32.dll")]
static extern bool GetCursorPos(out POINT lpPoint);

Однако WinAPI называет многие вещи «окнами»: элементы управления внутри окна также являются «окнами». Следовательно, вы можете не получить окно верхнего уровня в интуитивном смысле (вы можете получить переключатель, панель или что-то еще). Вы можете итеративно применять функцию GetParent, чтобы пройти вверх по иерархии GUI:

[DllImport("user32.dll", ExactSpelling=true, CharSet=CharSet.Auto)]
public static extern IntPtr GetParent(IntPtr hWnd);

Как только вы найдете окно без родителя, это окно будет окном верхнего уровня. Поскольку точка, которую вы изначально передали, принадлежит элементу управления, который не покрыт другим окном, то окно верхнего уровня обязательно должно принадлежать точке.

2 голосов
/ 10 октября 2010

После получения дескриптора окна вы можете использовать Control.FromHandle (), чтобы получить ссылку на элемент управления.Затем проверьте относительное положение мыши, чтобы увидеть, является ли это клиентской областью формы или элемента управления.Как это:

    private void timer1_Tick(object sender, EventArgs e) {
        var hdl = WindowFromPoint(Control.MousePosition);
        var ctl = Control.FromHandle(hdl);
        if (ctl != null) {
            var rel = ctl.PointToClient(Control.MousePosition);
            if (ctl.ClientRectangle.Contains(rel)) {
                Console.WriteLine("Found {0}", ctl.Name);
                return;
            }
        }
        Console.WriteLine("No match");
    }

    [System.Runtime.InteropServices.DllImport("user32.dll")]
    private static extern IntPtr WindowFromPoint(Point loc);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...