The Lazy Coder
The Lazy Coder

Reputation: 11838

Is there a way to hook mouse events for a specific button in a windows form

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 FindWindowEx will help me find the window handle that I want to trap these events from.

I just don't know how to make it give me the Events from specific window handles. Or how to Determine what handle the message is supposed to be going to.

Anyone else with experience in this I would greatly appreciate some good

EDIT

Alternatively the code to a Spy++ tool in C# or a working copy of ManagedSpy or something similar. I want to learn to navigate the Window Handle Hierarchy and hook windows events from those.

Upvotes: 3

Views: 3640

Answers (2)

sri
sri

Reputation: 1005

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

Upvotes: 1

shf301
shf301

Reputation: 31404

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

Upvotes: 1

Related Questions