I want to hook the WM_MOUSEDOWN and WM_MOUSEUP events from a specific button inside a specific window. I am thinking that SetWindowsHookEx will hook the messages I want. and Fin
SetWindowsHookEx
can be used to hook a specific thread or all threads. You cant hook a specific handle. You can get the specific thread or all threads of the windows forms application & hook them, but it doesn't solve your problem, this is just a performance consideration.
In the callback of the MouseProc
you can filter the events WM_LBUTTONDOWN
, WM_LBUTTONUP
using wParam
.
You can get handle to the window to which this mouse event is going from lParam
MOUSEHOOKSTRUCT * pMouseHookStruct = (MOUSEHOOKSTRUCT *) lParam;
HWMD hWnd = pMouseHookStruct->hwnd;
from hwnd
you can get all details of the window, and you can check if it is the same windows forms window.
If you want mouse events of only a specific button, you can get the UI Object details from the mouse clicked point & filter the events accordingly (using UIAutomation
)
CoCreateInstance(__uuidof(CUIAutomation), NULL, CLSCTX_INPROC_SERVER, __uuidof(IUIAutomation), (void**)&pAutomation);
pAutomation->ElementFromPoint(*pPoint, &pIUIAutomationElement);
You can get the button name
, rect coordinates
, hot keys
etc from IUIAutomationElement
You can't make SetWindowsHookEx only give you thew events from a single window handle, but you can filter it yourself. If you are using the WH_CALLWNDPROC
or WH_CALLWNDPROCRET
(which you need to use to get the mouse messages you are interested in), the lParam
value of CallWndProc and CallWndRetProc are a structure that contain the window handle of the control processing the message.
So in your SetWindowsHookEx
call back you only need to check that the message is for the window you are filtering.
For example:
static HWND s_hWndButton;
.....
SetWindowsHookEx(WH_CALLWNDPROC, ButtonHookProc, ....);
.....
LRESULT CALLBACK CallWndProc(int nCode, WPARAM wParam, LPARAM lParam) {
if (nCode >= 0) {
CWPSTRUCT* cp = (CWPSTRUCT*)lParam;
if (cp->hWnd == s_hWndButton) {
if (cp->Msg == WM_MOUSEUP || cp->Msg == WM_MOUSEDOWN) {
// Your logic goes here
}
}
}
Return CallNextHookEx(NULL, nCode, wParam, lParam);
}
Pretty much the same logic would apply for WH_CALLWNDPROCRET