3

In my c# project I’m trying to intercept mouse clicks from another program, but only the ones that come from a certain hwnd as well… I’ve read here that I can filter my messages using the lParam but I’ve not succeeded to cast it to something I can actually get Hwnd’s back from.

This is how I set up the global mouse hook:

SetWindowsHookEx(WH_MOUSE_LL, s_MouseDelegate, IntPtr.Zero, 0);

I then catch the messages in this function:

private static int MouseHookProc(int nCode, int wParam, IntPtr lParam)
{
    if (nCode >= 0)
    {
          switch (wParam)
          {
               case WM_LBUTTONDOWN:
                    mouseDown = true;
                    mouseUp = false;
                    break;
               case WM_LBUTTONUP:
                    mouseUp = true;
                    mouseDown = false;
                    break;
          }
     }
     return CallNextHookEx(s_MouseHookHandle, nCode, wParam, lParam);
}

I then made the CWPSTRUCT like this:

[StructLayout(LayoutKind.Sequential)]
public struct CWPSTRUCT
{
    public IntPtr lparam;
    public IntPtr wparam;
    public int message;
    public IntPtr hwnd;
}

And here's the part where it probably goes wrong...I’ve tried 2 things:

CWPSTRUCT cwp = (CWPSTRUCT)Marshal.PtrToStructure(lParam, typeof(CWPSTRUCT));

Or the unsafe version this is where I got it from:

CWPSTRUCT* cp = (CWPSTRUCT*)lParam;

When using the first option I always get 0 for the hwnd part and with the unsafe version I just get nothing... I don’t really know what I’m doing wrong here. Any help would be appreciated :)

Thanks

Community
  • 1
  • 1
VincentC
  • 245
  • 4
  • 14

1 Answers1

4

Since you're hooking WH_MOUSE_LL, lParam contains pointer to MSLLHOOKSTRUCT instead of CWPSTRUCT (which is actually for WH_CALLWNDPROC).

So you should define the following structures:

[StructLayout(LayoutKind.Sequential)]
public struct POINT
{
    public int X;
    public int Y;
}

[StructLayout(LayoutKind.Sequential)]
public struct MSLLHOOKSTRUCT
{
    public POINT pt;
    public int mouseData;
    public int flags;
    public int time;
    public UIntPtr dwExtraInfo;
}

And marshal lParam to MSLLHOOKSTRUCT:

MSLLHOOKSTRUCT mouseLowLevelHook = (MSLLHOOKSTRUCT)Marshal.PtrToStructure(lParam,
    typeof(MSLLHOOKSTRUCT));

Also, you should change wParam's type from int to IntPtr, so it will work properly on 64-bit platforms.

Additional links:

Nick Hill
  • 4,867
  • 3
  • 23
  • 29
  • Thank you very much! This has solved my problem. I do have 1 small question left... the UIntPtr dwExtraInfo, what exactly does it contain? (Additional information associated with the message.) Because I thought it might be the window where I clicked on? But I don't think it is because it's 0 as well. I got the handle of the window I clicked on now by using [WindowFromPoint](http://msdn.microsoft.com/en-us/library/windows/desktop/ms633558%28v=vs.85%29.aspx) is that the correct way? – VincentC Oct 14 '12 at 09:24
  • @VincentC `dwExtraInfo` seems to be a reference to the application-specific extra info. – Nick Hill Oct 14 '12 at 14:19
  • @VincentC Yes, you can use [`WindowFromPoint`](http://msdn.microsoft.com/en-us/library/windows/desktop/ms633558%28v=vs.85%29.aspx) to get hwnd. Although it would be better to create a global hook for [`WH_MOUSE`](http://msdn.microsoft.com/en-us/library/windows/desktop/ms644988(v=vs.85).aspx) or [`WH_CALLWNDPROC`](http://msdn.microsoft.com/en-us/library/windows/desktop/ms644975(v=vs.85).aspx). You can read about it here: [Using Window Messages to Implement Global System Hooks in C#](http://www.codeproject.com/Articles/18638/Using-Window-Messages-to-Implement-Global-System-H) – Nick Hill Oct 14 '12 at 14:21