首页 > 解决方案 > 使用 .net 核心工作的全局鼠标(和可选的键盘)挂钩

问题描述

我正在尝试在 .net core 3.1 中全局检测水平滚轮的移动(或至少是任何鼠标滚轮的移动)。我想构建此应用程序以同时适用于 Windows 10 x64 和 arm-linux。但是,我只需要 Windows 上的钩子功能。我尝试使用包含 System.Windows.Forms MouseEvents的WindowsHook以及它所基于的普通MouseKeyHook 。两者都没有工作。我的SetWindowsHookEx原始输入 API的实现也是如此. 在 .net 核心应用程序中尝试它们只会导致一旦侦听器就位并且没有实际触发任何事件时就会出现巨大的输入延迟。我现在搜索了两天,我开始相信你需要成为一个向导才能让这样一个全局挂钩在 .net 核心中工作。帮助将不胜感激!

编辑:这是我第一次使用钩子并做低级的事情,所以我不能 100% 理解所有这些。我这里只有这个代码片段。对于 WindowsHook 和 MouseKeyHook,我只使用您可以在相应链接的 github 项目中找到的示例。

这是 SetWindowsHookEx 版本,我只是调用构造函数让它运行,它甚至没有捕获 hscroll 我相信:

using System;
using System.Runtime.InteropServices;

class Intercept_Mouse
{
    private static LowLevelMouseProc _proc = HookCallback;
    private delegate IntPtr LowLevelMouseProc(int nCode, IntPtr wParam, IntPtr lParam);
    private static IntPtr _hookID = IntPtr.Zero;


    public Intercept_Mouse()
    {
        _hookID = SetWindowsHookEx(WH_MOUSE_LL, _proc, IntPtr.Zero, 0);
    }

    private static IntPtr HookCallback(int nCode, IntPtr wParam, IntPtr lParam)
    {
        if (nCode >= 0 && (MouseMessages.WM_LBUTTONDOWN == (MouseMessages)wParam))
        {
            Console.WriteLine("Clicked");
        }
        return CallNextHookEx(_hookID, nCode, wParam, lParam);
    }


    private const int WH_MOUSE_LL = 14;

    private enum MouseMessages
    {
        WM_LBUTTONDOWN = 0x0201,
        WM_LBUTTONUP = 0x0202,
        WM_MOUSEMOVE = 0x0200,
        WM_MOUSEWHEEL = 0x020A,
        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#.net-corehook

解决方案


推荐阅读