【问题标题】:C# Is there a way to detect a mouse click from additional mouse buttons with hooks?C# 有没有办法从带有钩子的其他鼠标按钮中检测鼠标点击?
【发布时间】:2018-05-08 17:17:00
【问题描述】:

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

当我谈到特殊的鼠标按钮时,我指的是其他按钮,例如游戏鼠标。示例: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);
        }
    }
}

谢谢。

【问题讨论】:

  • 大多数游戏鼠标不是将“特殊按钮”映射到其设备驱动程序中的键盘快捷键吗?
  • 也许,我会尝试在调试模式下找到键盘快捷键,我会及时更新。感谢您的提示。
  • 为什么是调试模式?只需进入设备驱动程序的设置...您可以通过调试来验证您的发现,但只是查找它应该更快。
  • 如果您还没有,请参阅 About Mouse Input - XBUTTONSWM_APPCOMMAND 上的 MSDN。

标签: c# winforms mouseevent hook mouse-hook


【解决方案1】:

如果我理解您是正确的,您希望在单击其他鼠标按钮后找到正在发送的WindowsMessages。为了检测那些我建议你创建一个自定义的MessageFilter,它实现了接口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;
    }
}

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

要激活这个MessageFilter,你要做的就是把这个添加到你的应用程序中,我建议在InitializeComponent()之后的构造函数中这样做。

MessageFilter msgFilter = new MessageFilter();

Application.AddMessageFilter(msgFilter);

【讨论】:

  • 如果我错了请告诉我,但我需要捕捉任何点击(即使是正常的点击),即使我没有专注于窗口(即 APM 计算器)我也需要捕捉那些)。所以你的解决方案在这种情况下不起作用对吗?那是我的错,实际上我应该对此更准确。但是感谢您提供的示例,以后会有所帮助!
猜你喜欢
  • 2021-03-07
  • 1970-01-01
  • 1970-01-01
  • 2021-08-28
  • 1970-01-01
  • 1970-01-01
  • 2020-04-29
  • 1970-01-01
  • 2020-04-18
相关资源
最近更新 更多