使用setwindowshookex在C#中设置鼠标钩子:wparam和lparam总是返回常量

时间:2017-07-11 06:09:47

标签: c# .net hook

我正在使用setwindowshookex

在C#中实现鼠标挂钩

我有代码可以检测何时触发鼠标事件并将数据传递给指定的回调函数,根据我见过的其他地方的大量示例代码,这些代码应符合mouseProc回调函数,该函数将int作为“ ncode“(我无法弄清楚它是什么。),wParam和lParam。

根据我所见,通过wParam提供事件类型,并通过lParam提供其他信息。

事件类型通过文档中详细列出的here枚举来表示。

然而,与这些枚举相关联的文档表明它们是从WindowProc回调返回的,其中wParam和lParam分别与修改键和鼠标的xy坐标相关联。

我找不到详细说明我目前正在使用的回调的文档,所以我不确定我是不是在寻找正确的地方,或者是否已经更新了.NET。

无论回调中的3个或4个参数如何,wParam和lParam的值始终是常量。 wParam似乎与先前讨论的枚举相对应(例如,对于左键单击,我接收十六进制0x0201)。但是,lParam是一些常数,我无法与任何东西联系起来。它似乎不是指向有意义数据的地址。

这是我的代码的简短工作示例:

using System;
using System.Diagnostics;
using System.Runtime.InteropServices;

class MouseMonitor
{
    [DllImport("user32", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall, SetLastError = true)]
    public static extern int SetWindowsHookEx(Utils.HookType idHook, MouseProc lpfn, int hInstance, int threadId);

    [DllImport("user32", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall, SetLastError = true)]
    public static extern int CallNextHookEx(int idHook, int nCode, IntPtr wParam, IntPtr lParam);

    [DllImport("kernel32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall, SetLastError = true)]
    public static extern int GetCurrentThreadId();

    [DllImport("kernel32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall, SetLastError = true)]
    public static extern int GetModuleHandle(string lpModuleName);

    public delegate int MouseProc(int nCode, IntPtr wParam, IntPtr lParam);

    private int hookID = 0;
    private MouseProc hookCallback = null;

    public MouseMonitor()
    {
        this.hookCallback = new MouseProc(HookCallback);

        using (Process curProcess = Process.GetCurrentProcess())
        using (ProcessModule curModule = curProcess.MainModule)
        {
             this.hookID = SetWindowsHookEx(Utils.HookType.WH_MOUSE_LL, this.hookCallback, Utils.GetModuleHandle(curModule.ModuleName), 0);
        }
    }

    private int HookCallback(int nCode,  IntPtr wParam, IntPtr lParam)
    {
        if (MouseMessages.WM_LBUTTONDOWN == (MouseMessages)wParam)
        {
             // Do something.
        }
        return Utils.CallNextHookEx(this.hookID, nCode, wParam, lParam);
    }
}

所以我不确定我对文档的理解是否不正确,而且我没有使用正确的回调或其他内容。我至少会期望每次都有不同的价值,即使它是垃圾还是坏的。

1 个答案:

答案 0 :(得分:0)

根据MSDN,您的lParamMOUSEHOOKSTRUCT的指针,可以使用this technique轻松地从指针转换为结构。

工作代码如下所示:

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

    [StructLayout(LayoutKind.Sequential)]
    struct MOUSEHOOKSTRUCT
    {
        public Point pt;
        public IntPtr hwnd;
        public uint wHitTestCode;
        public IntPtr dwExtraInfo;
    }

    private int HookCallback(int nCode, IntPtr wParam, IntPtr lParam)
    {
        if (MouseMessages.WM_LBUTTONDOWN == (MouseMessages)wParam)
        {
            // Do something.
            var mhs = Marshal.PtrToStructure<MOUSEHOOKSTRUCT>(lParam);
            Console.WriteLine($"point: {mhs.pt.X} {mhs.pt.Y}");
        }
        return CallNextHookEx(this.hookID, nCode, wParam, lParam);
    }