Сообщения, поступающие от мыши
Мышь может порождать много сообщений, всего их 22! Однако большинство из них вы можете благополучно проигнорировать, передав эти сообщения "всеядной" функции DefWindowProc. Сообщения, поступающие от мыши, содержат информацию о текущем расположении курсора, о его расположении в момент, когда вы нажимаете на клавиши мыши, и другую аналогичную информацию.
Куда попадают сообщения от мыши?
Существует два режима, определяющих два способа распределения сообщений от мыши.
В первом режиме, который установлен по умолчанию, сообщения от мыши направляются функции окна, расположенного под курсором мыши. Если в главном окне приложения создано дочернее окно и курсор мыши располагается над дочерним окном, сообщения мыши попадут в функцию дочернего окна, но не в функцию главного окна приложения. Это же касается и временных (pop-up) окон.
Во втором режиме окно может захватить мышь для монопольного использования. В этом случае функция этого окна будет всегда получать все сообщения мыши, независимо от расположения курсора мыши. Для того чтобы захватить мышь, приложение должно вызвать функцию SetCapture:
HWND WINAPI SetCapture(HWND hwnd);
Параметр hwnd функции указывает идентификатор окна, которое будет получать все сообщения от мыши вне зависимости от расположения курсора.
Функция SetCapture возвращает идентификатор окна, которое захватывало мышь до вызова функции или NULL, если такого окна не было.
Функция ReleaseCapture возвращает нормальный режим обработки сообщений мыши:
void WINAPI ReleaseCapture(void);
Эта функция не имеет параметров и не возвращает никакого значения.
Функция GetCapture позволяет определить идентификатор окна, захватившего мышь:
HWND WINAPI GetCapture(void);
Если ни одно окно не захватывало мышь, эта функция возвратит значение NULL.
В любом случае на получение сообщений от мыши никак не влияет факт приобретения или потери окном фокуса ввода.
Приведем полный список сообщений, поступающих от мыши.
Сообщение | Описание |
WM_LBUTTONDBLCLK | Двойной щелчок левой клавишей мыши во внутренней (client) области окна |
WM_LBUTTONDOWN | Нажата левая клавиша мыши во внутренней области окна |
WM_LBUTTONUP | Отпущена левая клавиша мыши во внутренней области окна |
WM_MBUTTONDBLCLK | Двойной щелчок средней клавишей мыши во внутренней области окна |
WM_MBUTTONDOWN | Нажата средняя клавиша мыши во внутренней области окна |
WM_MBUTTOMUP | Отпущена средняя клавиша мыши во внутренней области окна |
WM_MOUSEMOVE | Перемещение курсора мыши во внутренней области окна |
WM_RBUTTONDBLCLK | Двойной щелчок правой клавишей мыши во внутренней области окна |
WM_RBUTTONDOWN | Нажата правая клавиша мыши во внутренней области окна |
WM_RBUTTONUP | Отпущена правая клавиша мыши во внутренней области окна |
WM_NCHITTEST | Перемещение мыши в любом месте экрана |
WM_MOUSEACTIVE | Нажата клавиша мыши над неактивным окном |
WM_NCLBUTTONDBLCLK | Двойной щелчок левой клавишей мыши во внешней (non-client) области окна |
WM_NCLBUTTONDOWN | Нажата левая клавиша мыши во внешней области окна |
WM_NCLBUTTONUP | Отпущена левая клавиша мыши во внешней области окна |
WM_NCMBUTTONDBLCLK | Двойной щелчок средней клавишей мыши во внешней области окна |
WM_NCMBUTTONDOWN | Нажата средняя клавиша мыши во внешней области окна |
WM_NCMBUTTOMUP | Отпущена средняя клавиша мыши во внешней области окна |
WM_NCMOUSEMOVE | Перемещение курсора мыши во внешней области окна |
WM_NCRBUTTONDBLCLK | Двойной щелчок правой клавишей мыши во внешней области окна |
WM_NCRBUTTONDOWN | Нажата правая клавиша мыши во внешней области окна |
WM_NCRBUTTONUP | Отпущена правая клавиша мыши во внешней области окна |
Из приведенных выше 22 сообщений 21 сообщение образуется из сообщения WM_NCHITTEST. Это сообщение генерируется драйвером мыши при любых перемещениях мыши. Разумеется, драйвер не отслеживает перемещение мыши для каждого пиксела экрана. Период возникновения сообщений WM_NCHITTEST зависит от скорости перемещения мыши, параметров драйвера, аппаратуры мыши и т. п.
Сообщение WM_NCHITTEST не использует параметр wParam. В младшем слове параметра lParam передается горизонтальная позиция курсора мыши, а в старшем - вертикальная. Координаты вычисляются относительно верхнего левого угла экрана.
Приложения редко обрабатывают сообщение WM_NCHITTEST, обычно оно передается функции DefWindowProc. Получив это сообщение, функция DefWindowProc определяет положение курсора мыши относительно расположенных на экране объектов и возвращает одно из приведенных ниже значений, описанных в файле windows.h).
Значение | Расположение курсора мыши |
HTBORDER | На рамке окна, которое создано без толстой рамки, предназначенной для изменения размера окна |
HTBOTTOM | На нижней горизонтальной линии рамки окна |
HTBOTTOMLEFT | В левом нижнем углу рамки |
HTBOTTOMRIGHT | В правом нижнем углу рамки |
HTCAPTION | На заголовке окна (title-bar) |
HTCLIENT | Во внутренней области окна (client area) |
HTERROR | Над поверхностью экрана или на линии, разделяющей различные окна. Дополнительно функция DefWindowProc выдает звуковой сигнал |
HTGROWBOX | В области изменения размера окна (size box) |
HTHSCROLL | На горизонтальной полосе просмотра |
HTLEFT | На левой вертикальной линии рамки окна |
HTMAXBUTTON | На кнопке максимизиции |
HTMENU | В области меню |
HTMINBUTTON | На кнопке минимизации |
HTNOWHERE | Над поверхностью экрана или на линии, разделяющей различные окна |
HTREDUCE | В области минимизации |
HTRIGHT | На правой вертикальной линии рамки окна |
HTSIZE | В области изменения размера окна (size box). То же самое, что и HTGROWBOX |
HTSYSMENU | В области системного меню |
HTTOP | На верхней горизонтальной линии рамки окна |
HTTOPLEFT | В верхнем левом углу рамки окна |
HTTOPRIGHT | В правом верхнем углу рамки окна |
HTTRANSPARENT | В окне, которое перекрыто другим окном |
HTVSCROLL | На вертикальной полосе просмотра |
HTZOOM | В области максимизиции |
После обработки сообщения WM_HITTEST Windows анализирует расположение курсора и генерирует одно из сообщений, описанных выше.
Если курсор находится во внутренней области окна (client area), функция DefWindowProc возвращает значение HTCLIENT. В этом случае функция окна, над которой находится курсор мыши (или функция окна, захватившая мышь), будет получать сообщения о событиях во внутренней области окна. Это все описанные выше сообщения, кроме сообщений с префиксом WM_NC и сообщения WM_MOUSEACTIVATE (сочетание букв NC в символическом имени сообщения означает Non Client).
Внешняя область окна (Non Client) соответствует пространству между внешним контуром окна и его внутренней областью. В этом пространстве располагаются такие элементы, как рамка окна, кнопки максимизиции и минимизации, системное меню и меню окна и т. п.
Если при обработке сообщения WM_HITTEST выясняется, что курсор мыши расположен во внешней области окна, функция окна получает сообщения мыши с префиксом WM_NC.
Эти сообщения также редко используются приложениями и обычно передаются функции DefWindowProc. Обработка сообщений с префиксом WM_NC заключается в перемещении окна, изменении его размеров, активизации меню и т. д., в зависимости от самого сообщения.
Ваше приложение может перехватить сообщения с префиксом WM_NC, но, если эти сообщения не будут переданы функции DefWindowProc, Windows не сможет выполнять соответствующие им действия.