Страницы

Поиск по вопросам

вторник, 11 июня 2019 г.

Обработка события нажатия правого клика мыши по кнопке

Только недавно начал разбираться с WinApi, и в процессе решения лабораторной возник вопрос: как обработать нажатие правой кнопки мыши по отдельно взятой кнопки окна? Событие WM_RBUTTONDOWN определяет нажатие правой кнопки мыши по всему окну, поэтому оно мне не подходит. Если не затруднит, можете предоставить пример кода, а то я только начинающий. Заранее благодарю за ответ.


Ответ

Вообще, подобный подход (использование правой кнопки мыши на кнопке) является плохой практикой в разработке GUI, так как нарушает ожидаемое пользователем поведение кнопки.
Если кнопка подразумевает дополнительный набор связанных с ней действий, используйте кнопку с маленькой кнопочкой-стрелкой на её правой стороне (такие имеют оконный класс BS_SPLITBUTTON, либо BS_DEFSPLITBUTTON):
    
Если же вам по какой-то причине нужна обработка именно правой кнопки мыши (и я очень надеюсь, что это учебное задание, а не реальная разработка), то единственный способ пойти против рекомендаций Microsoft — перехватывать («сабклассить») нужное вам оконное сообщение WM_RBUTTONDOWN
#include #include #include
// Указатель на исходный обработчик кнопки WNDPROC oldButtonProc;
// Обработчик нажатия правой кнопки мыши // Замечание: bDblCkick всегда равен FALSE static void onRButtonClick(HWND hwnd, BOOL bDblClick, int x, int y, UINT uKey) { // ... }
// Перехватчик static LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { // Обрабатываем WM_RBUTTONDOWN, а остальное передаём обработчику кнопки по умолчанию // Для удобства воспользуемся message crackers из switch(uMsg) { HANDLE_MSG(hwnd, WM_RBUTTONDOWN, onRButtonClick);
default: return oldButtonProc(hwnd, uMsg, wParam, lParam); } }
// Где-то в коде надо назначить наш обработчик нужной кнопке следующим образом // (для удобства оформил всё в отдельную функцию. hButtonWnd — hwnd нужной кнопки): void subclassButton(HWND hButtonWnd) { // Преобразуем типы без нарушения strict aliasing rule const WNDPROC newProc = WindowProc; LONG_PTR newValue; #if __cplusplus >= 201103L static_assert(sizeof(newValue) == sizeof(newProc), "incompatible conversion"); #endif memcpy(&newValue, &newProc, sizeof(newProc));
const LONG_PTR oldValue = SetWindowLongPtr(hButtonWnd, GWLP_WNDPROC, newValue);
#if __cplusplus >= 201103L static_assert(sizeof(oldButtonProc) == sizeof(oldValue), "incompatible conversion"); #endif memcpy(&oldButtonProc, &oldValue, sizeof(oldValue)); }

Комментариев нет:

Отправить комментарий