You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Windows下用C++捕获雷蛇鼠标HID包遇阻,求解决方案

替代HID API捕获雷蛇Deathadder鼠标数据包的方案

先明确你遇到的核心问题:雷蛇Deathadder大概率被系统HID驱动独占占用,用户态程序哪怕用管理员权限也无法抢占设备;而Wireshark能捕获是因为它用的是内核级抓包机制,绕开了用户态的设备独占限制。hidapitester自动关闭则是因为设备检测到非官方客户端后主动断开,或是设备的HID报告描述符有特殊校验逻辑。

以下是几种可行的替代捕获方案:

1. 使用Windows Raw Input API

这是最推荐的方案,无需直接操作HID设备,通过系统输入队列获取原始鼠标数据,完美避开设备独占问题,甚至不需要管理员权限(除非要监听跨用户会话的输入)。

核心实现步骤:

  • 调用RegisterRawInputDevices注册鼠标设备,指定RIDEV_INPUTSINK标志让窗口在后台也能捕获输入。
  • 在窗口消息处理函数中监听WM_INPUT消息,通过GetRawInputData解析原始输入报告,提取额外按键的状态。

简单C++示例代码:

#include <Windows.h>
#include <iostream>

LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
    switch (uMsg) {
        case WM_INPUT: {
            UINT dataSize;
            GetRawInputData((HRAWINPUT)lParam, RID_INPUT, NULL, &dataSize, sizeof(RAWINPUTHEADER));
            LPBYTE rawData = new BYTE[dataSize];
            if (GetRawInputData((HRAWINPUT)lParam, RID_INPUT, rawData, &dataSize, sizeof(RAWINPUTHEADER)) == dataSize) {
                RAWINPUT* raw = (RAWINPUT*)rawData;
                if (raw->header.dwType == RIM_TYPEMOUSE) {
                    RAWMOUSE& mouse = raw->data.mouse;
                    // 检测额外按键(通常对应鼠标侧键4/5)
                    if (mouse.usButtonFlags & RI_MOUSE_BUTTON_4_DOWN) {
                        std::cout << "侧键4按下" << std::endl;
                        // 在这里执行你的宏逻辑
                    }
                    if (mouse.usButtonFlags & RI_MOUSE_BUTTON_5_DOWN) {
                        std::cout << "侧键5按下" << std::endl;
                        // 在这里执行你的宏逻辑
                    }
                }
            }
            delete[] rawData;
            break;
        }
        case WM_DESTROY:
            PostQuitMessage(0);
            return 0;
        default:
            return DefWindowProc(hwnd, uMsg, wParam, lParam);
    }
    return 0;
}

int main() {
    const wchar_t CLASS_NAME[] = L"RawInputMouseCapture";

    WNDCLASS wc = {0};
    wc.lpfnWndProc = WindowProc;
    wc.hInstance = GetModuleHandle(NULL);
    wc.lpszClassName = CLASS_NAME;
    RegisterClass(&wc);

    HWND hwnd = CreateWindowEx(
        0, CLASS_NAME, L"Mouse Macro Capture",
        0, CW_USEDEFAULT, CW_USEDEFAULT, 100, 100,
        NULL, NULL, GetModuleHandle(NULL), NULL
    );

    if (!hwnd) return 1;

    RAWINPUTDEVICE rid = {0};
    rid.usUsagePage = 0x01; // 通用桌面设备页
    rid.usUsage = 0x02;     // 鼠标设备
    rid.dwFlags = RIDEV_INPUTSINK; // 后台捕获输入
    rid.hwndTarget = hwnd;

    if (!RegisterRawInputDevices(&rid, 1, sizeof(rid))) {
        std::cout << "注册Raw Input失败,错误码:" << GetLastError() << std::endl;
        return 1;
    }

    MSG msg;
    while (GetMessage(&msg, NULL, 0, 0)) {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }

    return 0;
}

2. 编写内核级HID过滤驱动

通过内核驱动作为HID设备的过滤层,直接在内核态拦截鼠标的HID报告,完全绕开用户态的设备限制。

实现要点:

  • 注册HID过滤回调函数,在回调中捕获原始HID输入报告。
  • 通过IOCTL或者共享内存将数据传递到用户态程序处理。
  • 注意:Windows下驱动需要签名,或者临时开启测试模式才能加载。

3. 使用ETW追踪HID事件

利用Windows的Event Tracing for Windows (ETW)捕获系统级的HID输入事件:

  • 启用Microsoft-Windows-HIDClass提供者,追踪HIDClass_InputReport事件。
  • 可以用tracerpt工具解析追踪日志,或者编写程序直接订阅ETW事件获取实时数据。

4. 基于libusb直接操作USB设备

既然Wireshark能抓到USB数据包,可分析鼠标的HID报告格式,然后用libusb直接和设备通信:

  • 先卸载系统默认的HID驱动,改用libusb的驱动(比如用Zadig工具替换)。
  • 枚举USB设备,找到鼠标的输入端点,监听端点的原始数据。
  • 解析Wireshark捕获的数据包,提取额外按键对应的字节位,实现宏逻辑。

内容的提问来源于stack exchange,提问作者kurta999

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.31 08:56:07