3

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.

The Lazy Coder
  • 11,560
  • 4
  • 51
  • 69
  • You use WH_MOUSE, I'm still working with it, but from what I understand you can't use WH_MOUSE_LL to get local information (the hwnd you'd be looking for). From what I'm understanding now, the only way is to create a .dll file. – Mark Aven Feb 09 '19 at 05:34

2 Answers2

1

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

shf301
  • 31,086
  • 2
  • 52
  • 86
1

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

sri
  • 1,005
  • 1
  • 12
  • 26
  • So now each of your answers have competing Structures... are these the same structure ? – The Lazy Coder Oct 14 '11 at 01:28
  • @VolureDarkAngel: These are 2 different approaches, one is capturing all mouse events using WH_MOUSE hook, & the other is capturing all Windows Message events going to the windows – sri Oct 14 '11 at 02:17
  • Do you know of a good place to get more information on the low level hooking. Best practices and methods and the such ? – The Lazy Coder Oct 14 '11 at 02:19