Только недавно начал разбираться с WinApi, и в процессе решения лабораторной возник вопрос: как обработать нажатие правой кнопки мыши по отдельно взятой кнопки окна? Событие WM_RBUTTONDOWN определяет нажатие правой кнопки мыши по всему окну, поэтому оно мне не подходит. Если не затруднит, можете предоставить пример кода, а то я только начинающий. Заранее благодарю за ответ.
Ответ
Вообще, подобный подход (использование правой кнопки мыши на кнопке) является плохой практикой в разработке GUI, так как нарушает ожидаемое пользователем поведение кнопки.
Если кнопка подразумевает дополнительный набор связанных с ней действий, используйте кнопку с маленькой кнопочкой-стрелкой на её правой стороне (такие имеют оконный класс BS_SPLITBUTTON, либо BS_DEFSPLITBUTTON):
Если же вам по какой-то причине нужна обработка именно правой кнопки мыши (и я очень надеюсь, что это учебное задание, а не реальная разработка), то единственный способ пойти против рекомендаций Microsoft — перехватывать («сабклассить») нужное вам оконное сообщение WM_RBUTTONDOWN
#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 из
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));
}
Комментариев нет:
Отправить комментарий