3

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

当我谈论特殊鼠标按钮时,我指的是游戏鼠标等附加按钮。示例:罗技 G600

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

我已经找到了如何为常规按钮甚至导航按钮做到这一点,但我似乎找不到任何关于其他按钮的信息。

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

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);
        }
    }
}

谢谢。

4

1 回答 1

0

如果我理解您是正确的,您希望在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;
    }
}

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

激活MessageFilter它所要做的就是将此添加到您的应用程序中,我建议在构造函数之后执行它InitializeComponent()

MessageFilter msgFilter = new MessageFilter();

Application.AddMessageFilter(msgFilter);
于 2018-03-12T15:29:57.687 回答