在 MouseButtonEventArgs 构造函数中为 MouseDevice 参数添加什么?

What do I put for the MouseDevice parameter in a MouseButtonEventArgs Constructor?

我正在用 WPF c# 创建一个应用程序,它需要能够分别检测鼠标向上单击和向下单击事件。为此,我使用了在网上找到的全局鼠标挂钩代码。代码的唯一问题是它使用 EventArgs 作为 EventHandler,因此每次我发送 MouseUp 和 MouseDown 时它都传递相同的函数。为了解决这个问题,我使用了 MouseButtonEventArgs 构造函数。我现在遇到的问题是构造函数需要 3 个参数:MouseDevice、timestamp 和 MouseButton,构造函数才能实际工作。我已经弄清楚时间戳和 MouseButton,但我不知道为 MouseDevice 添加什么。我在此处放置什么以使构造函数工作?这是我的低级鼠标钩子 class 代码。

using System;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Windows.Input;

namespace KeystrokeDisplay
{
    public static class MouseHook
    {
        public static event MouseEventHandler MouseAction = delegate {  };

        public static void Start()
        {
            _hookID = SetHook(_proc);


        }
        public static void stop()
        {
            UnhookWindowsHookEx(_hookID);
        }

        private static LowLevelMouseProc _proc = HookCallback;
        private static IntPtr _hookID = IntPtr.Zero;

        private static IntPtr SetHook(LowLevelMouseProc proc)
        {
            using (Process curProcess = Process.GetCurrentProcess())
            using (ProcessModule curModule = curProcess.MainModule)
            {
                return SetWindowsHookEx(WH_MOUSE_LL, proc,
                  GetModuleHandle(curModule.ModuleName), 0);
            }
        }

        private delegate IntPtr LowLevelMouseProc(int nCode, IntPtr wParam, IntPtr lParam);

        private static IntPtr HookCallback(int nCode, IntPtr wParam, IntPtr lParam)
        {
            if (nCode >= 0 && MouseMessages.WM_LBUTTONDOWN == (MouseMessages)wParam)
            {
                MSLLHOOKSTRUCT hookStruct = (MSLLHOOKSTRUCT)Marshal.PtrToStructure(lParam, typeof(MSLLHOOKSTRUCT));
                MouseAction(null, new MouseButtonEventArgs(mouse: ????????, timestamp: 0, button: MouseButton.Left)); 
            }
            if (nCode >= 0 && MouseMessages.WM_LBUTTONUP == (MouseMessages)wParam)
            {
                MSLLHOOKSTRUCT hookStruct = (MSLLHOOKSTRUCT)Marshal.PtrToStructure(lParam, typeof(MSLLHOOKSTRUCT));
                MouseAction(null, new MouseButtonEventArgs(mouse: ????????, timestamp: 0, button: MouseButton.Left)); 
            }
            return CallNextHookEx(_hookID, nCode, wParam, lParam);
        }

        public const int WH_MOUSE_LL = 14;

        public enum MouseMessages
        {
            WM_LBUTTONDOWN = 0x0201,
            WM_LBUTTONUP = 0x0202,
     
            WM_RBUTTONDOWN = 0x0204,
            WM_RBUTTONUP = 0x0205
        }

        [StructLayout(LayoutKind.Sequential)]
        private struct POINT
        {
            public int x;
            public int y;
        }

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

        [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        private static extern IntPtr SetWindowsHookEx(int idHook,
          LowLevelMouseProc lpfn, IntPtr hMod, uint dwThreadId);

        [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        [return: MarshalAs(UnmanagedType.Bool)]
        private static extern bool UnhookWindowsHookEx(IntPtr hhk);

        [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        private static extern IntPtr CallNextHookEx(IntPtr hhk, int nCode,
          IntPtr wParam, IntPtr lParam);

        [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        private static extern IntPtr GetModuleHandle(string lpModuleName);


    }
}

我该如何解决这个问题?另外,我对 c# 还很陌生,所以我可能需要一些额外的帮助来理解你的答案。

我看不出有任何理由使用 MouseEventHandler

您想分别检测鼠标向上单击和向下单击事件,因此您可以为鼠标向上单击和向下单击创建两个委托并传递自己的事件参数。您只对按下哪个鼠标按钮感兴趣。

public delegate void MouseUpEventHandler(object sender, MyMouseEventArgs e);
public delegate void MouseDownEventHandler(object sender, MyMouseEventArgs e);

public class MyMouseEventArgs : EventArgs
{
    public MouseButton MouseButton { get; }

    public MyMouseEventArgs(MouseButton mouseButton)
    {
        MouseButton = mouseButton;
    }
}

然后替换

public static event MouseEventHandler MouseAction = delegate {  };

public static event MouseUpEventHandler MouseUpAction = delegate {  };
public static event MouseDownEventHandler MouseDownAction = delegate {  };

HookCallback中调用MouseDownActionMouseUpAction

private static IntPtr HookCallback(int nCode, IntPtr wParam, IntPtr lParam)
{
    if (nCode >= 0 && MouseMessages.WM_LBUTTONDOWN == (MouseMessages)wParam)
    {
        MSLLHOOKSTRUCT hookStruct = (MSLLHOOKSTRUCT)Marshal.PtrToStructure(lParam, typeof(MSLLHOOKSTRUCT));
        MouseDownAction(null, new MyMouseEventArgs(MouseButton.Left)); 
    }
    if (nCode >= 0 && MouseMessages.WM_LBUTTONUP == (MouseMessages)wParam)
    {
        MSLLHOOKSTRUCT hookStruct = (MSLLHOOKSTRUCT)Marshal.PtrToStructure(lParam, typeof(MSLLHOOKSTRUCT));
        MouseUpAction(null, new MyMouseEventArgs(MouseButton.Left)); 
        }
        return CallNextHookEx(_hookID, nCode, wParam, lParam);
    }