C# 有没有办法通过带钩子(Hook)的附加鼠标按钮检测鼠标点击?

标签 c# winforms mouseevent hook mouse-hook

我目前正在从事一个个人项目,我正在尝试创建类似 APM 计算器的项目。为了实现它,我需要能够检测到任何按下的键和任何鼠标点击。我正在使用钩子(Hook)来捕捉键盘事件和鼠标事件,但我找不到任何方法来捕捉特殊的鼠标按钮点击...

当我谈论特殊鼠标按钮时,我指的是游戏鼠标上的其他按钮。示例:Logitech G600

我想知道是否有任何方法可以检测任何鼠标按钮或特殊鼠标按钮的鼠标点击?

我已经找到了如何为 conventional buttons 甚至 the navigation buttons 做这件事,但我似乎找不到任何关于附加按钮的信息。

这是我删除所有键盘部分的代码:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.ComponentModel;
using System.Diagnostics;
using System.Text;
using System.Windows.Input;

namespace MouseHook
{
    static class Program
    {
        private const int WH_MOUSE_LL = 14;
        private static LowLevelMouseProc _procMouse = HookCallbackMouse;
        private static IntPtr _hookIDMouse = IntPtr.Zero;

        private enum MouseMessages
        {
            WM_LBUTTONDOWN = 0x0201,
            WM_LBUTTONUP = 0x0202,
            WM_MOUSEMOVE = 0x0200,
            WM_MOUSEWHEEL = 0x020A,
            WM_RBUTTONDOWN = 0x0204,
            WM_RBUTTONUP = 0x0205,
            WM_XBUTTONDOWN = 0x020B

            // MISSING ADDITIONAL BUTTONS
        }

        [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        private static extern IntPtr SetWindowsHookEx(int idHook, LowLevelKeyboardProc 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);

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

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

        [STAThread]
        static void Main(string[] args)
        {
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);

            _hookIDMouse = SetHookMouse(_procMouse);

            Application.Run(new Form1());

            UnhookWindowsHookEx(_hookIDMouse);
        }

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

        private static IntPtr HookCallbackMouse(int nCode, IntPtr wParam, IntPtr lParam)
        {
            // DEAL WITH ANY BUTTON OR ADDITIONAL BUTTON MOUSE

            return CallNextHookEx(_hookIDMouse, nCode, wParam, lParam);
        }
    }
}

谢谢。

最佳答案

如果我理解你更正你想找到 WindowsMessages单击其他鼠标按钮后即会发送。为了检测这些,我建议您创建自定义 MessageFilter , 它实现了接口(interface) IMessageFilter .

class MessageFilter : IMessageFilter
{
    int[] msgToIgnore = new int[] {512, 799, 49632, 49446, 1847, 15, 96, 275, 160, 1848, 674 , 513, 675, 514, 280, 161, 274, 673, 515, 516, 517, 518, 519, 520, 521, 522, 163, 164, 167, 168, 169, 165, 166};

    public bool PreFilterMessage(ref Message m)
    {
        bool match = false;

        foreach (var msg in msgToIgnore)
        {
            if (m.Msg == msg)
                match = true;
        }

        if (!match)
        {
            MessageBox.Show(m.Msg.ToString());
            return true;
        }
        else
            return false;
    }
}

A MessageFilter过滤每一个WindowsMessage正在发送到您的应用程序。所以我基本上添加了 msgToIgnore数组忽略所有其他基本 WindowsMessages ,就像任何正常的鼠标点击、移动……或应用程序启动时发生的任何事情一样。 (我用一个空的普通表单对其进行了测试,然后在表单的每个部分上单击、双击、拖动……)这将忽略所有这些 WindowsMessages , 但是一旦你发送另一个 WindowsMessage ,所以例如你点击额外的鼠标按钮,WindowsMessage将显示在 MessageBox 中.

激活此 MessageFilter 所需要做的一切是将这个添加到您的应用程序中,我建议在 InitializeComponent() 之后的构造函数中执行此操作.

MessageFilter msgFilter = new MessageFilter();

Application.AddMessageFilter(msgFilter);

关于C# 有没有办法通过带钩子(Hook)的附加鼠标按钮检测鼠标点击?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49238016/

相关文章:

java - 快速移动鼠标时防止出现虚线

c# - 无法在 C# 中的 File.Copy 后删除临时文件

c# - NBuilder - 创建嵌套对象时出现问题

c# - Visual C# 集合 "map"函数?

c# - Richtextbox.invoke,C#,窗体仍挂

c# - 在 multidotExtension 上意外添加了 SaveFileDialog 扩展

c# - 过滤数据绑定(bind)数据 GridView (带有组合框列)的数据 View 使其速度非常慢

javascript - 如何在此示例中添加 ondrag 鼠标事件

c# - 如何使用 MethodInfo.Invoke 将参数作为引用传递

html - <a href=...> 在 onclick div 中