正确使用GetRawInputBuffer

2023-12-12

我正在尝试使用 Win32 原始输入 API 以更高精度收集原始鼠标数据,但我似乎无法理解文档和样本完全为了GetRawInputBuffer.

当我的鼠标悬停在窗口上时,似乎什么也没有发生。当我单击或释放窗口标题栏时,我似乎只获得缓冲数据,即使如此,我也大多获得 0 移动值,并且never接收鼠标按钮的变化。我尽可能密切地跟踪样本,但在网上搜索却运气不佳。

下面是一个带有该问题的高度简化示例的窗口过程和主程序。

LRESULT CALLBACK MessageHandler(HWND WindowHandle, UINT Message, WPARAM wParameter, LPARAM lParameter)
{
    switch(Message)
    {
    case WM_DESTROY:
        {
            PostQuitMessage(0);
            return 0;
        }
        break;
    case WM_CLOSE:
        {
            DestroyWindow(WindowHandle);
            return 0;
        }
        break;
    case WM_INPUT: 
        {
            UINT RawInputSize;
            UINT Result;

            Result = GetRawInputBuffer(NULL, &(RawInputSize), sizeof(RAWINPUTHEADER));
            if(Result == -1)
            {
                DWORD ErrorCode = GetLastError();
                std::cout << "GetRawInputBuffer returned error code" << ErrorCode << std::endl;
            }
            else if(Result == 0 && RawInputSize != 0)
            {
                UINT AllocatedBufferByteCount = RawInputSize * 16;
                RAWINPUT* RawInputBuffer = reinterpret_cast<RAWINPUT*>(malloc(AllocatedBufferByteCount));

                UINT AllocatedBufferByteCountTwo = AllocatedBufferByteCount;
                Result = GetRawInputBuffer(RawInputBuffer, &(AllocatedBufferByteCountTwo), sizeof(RAWINPUTHEADER));
                if(Result == -1)
                {
                    DWORD ErrorCode = GetLastError();
                    std::cout << "GetRawInputBuffer returned error code" << ErrorCode << std::endl;
                }
                else if(Result != 0)
                {
                    UINT RawInputCount = Result;

                    DWORD MouseDeltaX = 0;
                    DWORD MouseDeltaY = 0;

                    bool ButtonsPressed[2] = {false, false};

                    RAWINPUT* RawInput = RawInputBuffer;
                    for(unsigned int i = 0; i < RawInputCount; ++i)
                    {
                        switch(RawInput->header.dwType) 
                        {
                        // Raw mouse movement data for high-resolution mice. 
                        case RIM_TYPEMOUSE:
                            {
                                MouseDeltaX += RawInput->data.mouse.lLastX;
                                MouseDeltaY += RawInput->data.mouse.lLastY;

                                ButtonsPressed[0] = ((RawInput->data.mouse.usButtonFlags & RI_MOUSE_LEFT_BUTTON_DOWN) == RI_MOUSE_LEFT_BUTTON_DOWN);
                                ButtonsPressed[1] = ((RawInput->data.mouse.usButtonFlags & RI_MOUSE_RIGHT_BUTTON_DOWN) == RI_MOUSE_RIGHT_BUTTON_DOWN);
                            }
                            break;
                        }

                        RawInput = NEXTRAWINPUTBLOCK(RawInput);
                    }
                    DefRawInputProc(&(RawInputBuffer), RawInputCount, sizeof(RAWINPUTHEADER));
                    std::cout << "Mouse moved (" << MouseDeltaX << ", " << MouseDeltaY << ")." << std::endl;

                    if(ButtonsPressed[0])
                    {
                        std::cout << "LMB pressed." << std::endl;
                    }
                    if(ButtonsPressed[1])
                    {
                        std::cout << "RMB pressed." << std::endl;
                    }
                }

                free(RawInputBuffer);
            }
            return 0;
        }
        break;
    default:
        {
            return DefWindowProc(WindowHandle, Message, wParameter, lParameter);
        }
        break;
    }
}

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd)
{
    // Initialize window strings.
    wchar_t WindowClassName[] = L"DominionWindowClass";
    wchar_t WindowCaption[] = L"Test Window";

    // Create the window class.
    WNDCLASSEX WindowClass;
    WindowClass.cbSize = sizeof(WindowClass);
    WindowClass.style = CS_OWNDC | CS_HREDRAW | CS_VREDRAW;
    WindowClass.lpfnWndProc = &(MessageHandler);
    WindowClass.cbClsExtra = 0;
    WindowClass.cbWndExtra = 0;
    WindowClass.hInstance = hInstance;
    WindowClass.hIcon = LoadIcon(hInstance, IDI_APPLICATION);
    WindowClass.hIconSm = LoadIcon(hInstance, IDI_APPLICATION);
    WindowClass.hCursor = LoadCursor(NULL, IDC_ARROW);
    WindowClass.hbrBackground = NULL;
    WindowClass.lpszMenuName = NULL; 
    WindowClass.lpszClassName = WindowClassName;

    // Register window class.
    RegisterClassEx(&WindowClass);

    // Setup window style flags.
    DWORD WindowStyles = WS_VISIBLE | WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU;
    DWORD ExWindowStyles = WS_EX_APPWINDOW;

    // Setup window rectangle area.
    RECT WindowArea;
    WindowArea.left = 0;
    WindowArea.top = 0;
    WindowArea.right = 1024;
    WindowArea.bottom = 768;

    AdjustWindowRectEx(&(WindowArea), WindowStyles, false, ExWindowStyles);

    // Window creation.
    HWND WindowHandle = CreateWindowEx(ExWindowStyles, WindowClass.lpszClassName, WindowCaption, WindowStyles, CW_USEDEFAULT, CW_USEDEFAULT, (WindowArea.right - WindowArea.left), (WindowArea.bottom - WindowArea.top), NULL, NULL, hInstance, NULL);

    // Display the window.
    ShowWindow(WindowHandle, SW_SHOWDEFAULT);
    UpdateWindow(WindowHandle);

    // Register devices for raw input.
    const unsigned int RawInputDeviceCount = 1;
    RAWINPUTDEVICE RawInputDevices[RawInputDeviceCount];

    memset(RawInputDevices, 0, RawInputDeviceCount * sizeof(RAWINPUTDEVICE));

    RAWINPUTDEVICE* MouseRawInputDevice;

    MouseRawInputDevice = RawInputDevices;
    MouseRawInputDevice->usUsagePage = 1;
    MouseRawInputDevice->usUsage = 2;
    MouseRawInputDevice->hwndTarget = WindowHandle;

    BOOL SuccessfullyRegisteredInput = RegisterRawInputDevices(RawInputDevices, RawInputDeviceCount, sizeof(RAWINPUTDEVICE));

    // Core loop.
    MSG Message;
    for(;;)
    {
        while(PeekMessage(&Message, NULL, 0, 0, PM_REMOVE))
        {
            TranslateMessage(&Message);
            DispatchMessage(&Message);
            if(Message.message == WM_QUIT)
            {
                break;
            }
        }

        if(Message.message == WM_QUIT)
        {
            break;
        }
    }

    // Unregister devices for raw input.
    memset(RawInputDevices, 0, RawInputDeviceCount * sizeof(RAWINPUTDEVICE));
    MouseRawInputDevice = RawInputDevices;
    MouseRawInputDevice->usUsagePage = 1;
    MouseRawInputDevice->usUsage = 2;
    MouseRawInputDevice->dwFlags = RIDEV_REMOVE;
    MouseRawInputDevice->hwndTarget = NULL;

    BOOL SuccessfullyUnregisteredInput = RegisterRawInputDevices(RawInputDevices, RawInputDeviceCount, sizeof(RAWINPUTDEVICE));

    return Message.wParam;
}

我想不出更简单的方法来试验原始输入 API。想法?


迟来的答复,但是GetRawInputBuffer似乎用于消息处理循环之外的轮询。使用GetRawInputData within WM_INPUT处理或使用GetRawInputBuffer在消息处理循环之外。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

正确使用GetRawInputBuffer 的相关文章

  • 如何等到我启动的程序使用完该文件后才删除该文件?

    我一直在寻找一种方法来打开通过 Delphi 应用程序及其适当的应用程序保存到我的计算机上的文件 该文件存储在 SQL 数据库中的 Varbinary 字段中 加载到内存流中 然后通过 TMemoryStream 的 SavetoFile
  • 自动从 C# 代码进行调试过程并读取寄存器值

    我正在寻找一种方法来读取某个地址的 edx 注册表 就像这个问题中所问的那样 读取eax寄存器 https stackoverflow com questions 16490906 read eax register 虽然我的解决方案需要用
  • 如何在另一个应用程序中挂钩 api 调用

    我正在尝试挂钩另一个应用程序的 ExtTextOut 和 DrawTextExt GDI 方法调用 我知道我需要使用 GetProcAddress 来查找 gdi32 dll 中那些方法的地址 并用我的函数的地址覆盖我想要挂钩的进程中的地址
  • 无法从 Windows 注册表查询值

    我为 Windows 注册表编写程序并尝试从中查询值 但即使我以管理员权限运行自己的程序 我也无法读取所有参数并收到错误代码 5 某些值的访问被拒绝 但同时标准的注册表可以向我展示这个价值 我做错了什么 我有一个注册表类RegistryCl
  • win32 Python - pythoncom 错误 - ImportError: 没有名为 pywintypes 的模块

    我正在尝试导入 pythoncom 但它给了我这个错误 Traceback 最近一次调用最后 文件 F Documents and Settings Emery Desktop Python 27 Try 第 2 行 位于 导入python
  • 如何使用 Visual C++ 在 win32 API 中创建圆形/圆形按钮

    我有一个 Visual C 中的 Window Win32 API 应用程序 我没有使用MFC 我必须创建一个带有位图图像的圆形 圆形按钮 我的应用程序有一个皮肤视图 任何人都可以帮助我完成这项任务吗 按钮是窗口 您可以使用 CreateW
  • GetDeviceCaps获取的物理屏幕尺寸不是我屏幕的实际物理尺寸

    在 Windows 7 下 我使用以下代码来获取屏幕的物理宽度 以毫米为单位 hSize 为 482 比实际尺寸约 310 用尺子测量 大得多 这是为什么 HDC screen GetDC NULL int hSize GetDeviceC
  • 将第二个显示器显示设置更改为复制

    我正在尝试以编程方式使第二个监视器具有重复的显示 我的下面的功能应该将第二个显示器的显示更改为 重复显示 即使第二个显示器显示第一个 主显示器上的所有内容 我的问题 当我运行我的函数时 它成功找到第二个监视器 并通过更改 DEVMODE d
  • 让 Windows 尝试读取文件

    我正在对 Windows 文件系统进行某种封装 当用户请求打开文件时 Windows 调用我的驱动程序来提供数据 在正常操作中 驱动程序返回缓存的文件内容 但是 在某些情况下 实际文件没有缓存 我需要从网络下载它 问题是是否有可能让 Win
  • 简单的 C++ 线程

    我正在尝试在 C Win32 中创建一个线程来运行一个简单的方法 我是 C 线程的新手 但对 C 中的线程非常熟悉 这是我想做的一些伪代码 static void MyMethod int data RunStuff data void R
  • 如何从具有管理员权限的应用程序接收键盘输入到非管理员应用程序?

    我编写了一个应用程序 该应用程序具有覆盖类型的窗口 可以通过热键显示和隐藏该窗口 而另一个应用程序具有焦点 所述另一个应用程序是一个以管理员权限运行的 DirectX 游戏 我已经尝试了 3 种可能的解决方案 以便在其他应用程序中按下我的热
  • 如何获取与Windows主题相关的图标?

    如何获取Windows中某个控件的图标 更具体地说 我想从 ListView 标题中获取排序箭头图标 我尝试使用以下方法来获取它 HRESULT GetSortArrowBmp HWND hwnd HEADERSORTARROWSTATES
  • 如何使用 COMMTIMEOUTS 等待字节可用但读取多个字节?

    我有一个 C 串行端口类 它具有用于读取操作的非阻塞和阻塞模式 对于阻塞模式 COMMTIMEOUTS cto GetCommTimeouts m hFile cto Set the new timeouts cto ReadInterva
  • WIN32,C++:是否可以在不隐藏窗口的情况下对窗口进行动画处理?

    我有一个编辑控件 一个文本字段 我想要为其设置动画 我想要的动画是它滑出 为该文本字段创建一条额外的线 我可以为我的文本字段设置动画并使其变大 但是要显示滑动动画 我首先必须隐藏它 这意味着整个文本字段会滑出 就像第一次从无到有一样 而不是
  • 使用 Windows (XP+) api 发送(串行)中断

    有没有比 setcommbreak delay clearcommbreak 序列更好的方法来发送串行中断 我必须与使用串行中断作为 115k2 上数据包开头的微控制器进行通信 而 setcommbreak 有两个问题 对于 115k2 中
  • 32 位 OpenFileDialog --> 64 位 System32?

    在 32 位程序中 如何让打开 保存文件对话框显示 64 位系统的 System32 文件夹中的文件 Wow64DisableWow64FsRedirection不起作用 因为由于某种原因它不适用于对话框 我猜是因为它位于不同的线程上 当然
  • 在 Windows 中从文件名获取驱动器号

    是否有 Windows API 函数可以从 Windows 路径中提取驱动器号 例如 U path to file txt U path to file txt 在正确整理的同时 relative path to file txt alte
  • 如何使用 win32com.client api 访问 MS Word 的脚注

    我正在尝试使用 win32com client api 访问 MS Word 文件的脚注 我已经用谷歌搜索过 但没能找到合适的方法 我使用 python docx 来实现上述目的 但我发现当前版本的 python docx 无法访问 MS
  • python+win32:检测窗口拖动

    有没有办法检测何时使用 python pywin32 在窗口中拖动不属于我的应用程序的窗口 我想对其进行设置 以便当我拖动标题与桌面边缘附近的图案匹配的窗口时 当松开鼠标时它会捕捉到边缘 我可以编写代码 以便在释放鼠标时将所有具有该标题的窗
  • Windows 目录永远不会包含临时文件的非 ASCII 字符?

    在 Windows 上使用 MinGW 7 3 0 由于 Windows 限制 Hunspell 无法从包含非 ASCII 字符的位置加载字典文件 我已经尝试了所有方法 1 现在我将文件复制到没有 ASCII 字符的路径 然后再将其交给 H

随机推荐

  • SQL 多个参数值

    SQL 2005 中有哪些选项可用于将多个值传递给存储过程 伪代码 在 C 代码中 List
  • 相机使用自定义相机预览渲染器不清楚

    我使用以下链接使用自定义渲染器显示相机预览https developer xamarin com guides xamarin forms application fundamentals custom renderer view I wa
  • 如何限制图片上传大小小于2mb?

    我有一个 htmlselect上传图像的选项 div class row smallMargin div class col sm 6 Attach Image div div class col sm 6 div div
  • 如何从hibernate+spring应用程序将csv文件导入mysql?

    我想将 csv 文件导入到 mysql 表中 我进行导入的原因是因为我有很多大文件 这些文件会在短时间内发送到我的服务器 尝试使用 java 逐行添加 但遇到了一堆不同的错误 例如休眠异常或 java 挂起 如果文件是 太大 导入速度非常快
  • ForEach - 打印项目和数值[重复]

    这个问题在这里已经有答案了 如何实现显示每个数组成员以及取决于列表计数的数值的 ForEach 结果 该数值会针对每个项目递增 例子是 1 火鸡 2 火腿 3 梅奥 struct EditorDirections View State pr
  • 4 列 CSS 布局 - 流体

    我正在绕圈子试图解决这个问题 HTML CSS div div class inner box clearfix div div div div
  • 获取点击的图片框数组的索引

    我正在动态创建一些图片框并单击图片框的事件 如下所示 Image myImage Image FromFile image Untitled6 png PictureBox txtTeamNames new PictureBox 5 for
  • 用于下载文档的 Alfresco REST API

    我想使用 Afresco REST API 下载文档 经过一番研究 我发现了这个 REST API alfresco s api node content property store type store id id 但我不知道如何传递参
  • 如何从servlet调用JavaScript函数

    我是网络开发新手 我有一个外部 JavaScript 文件 其中包含一个要显示的函数 包含错误详细信息的提示 我需要将错误消息传递给函数 我已经在servlet中编写了控制器 如何从我的 servlet 调用该 JavaScript 文件的
  • 处理退出状态 popen python

    我试图用 popen 处理状态退出 但它给出了一个错误 代码是 import os try res os popen ping c 4 www google com except IOError print ISPerror popen t
  • 奇怪的单元格地址非连续范围的行为:VBA

    我试图回答这个问题当我在 Excel 中遇到一些奇怪的 VBA 行为时 我写了一个非常简单的子程序来演示这个问题 Sub debugAddresses rng As Range Debug Print Whole range rng Add
  • 从 Android 中的通知开始新活动

    我想从状态栏通知启动一个活动 A 当活动 A 已经在前面时 我想完成该活动并重新启动活动 A 我该怎么做 查看有关创建状态栏通知的文档 这绝对涵盖了使用 Intent 和 PendingIntent 从通知启动和 Activity http
  • 从边列表构建所有哈密顿路径

    我无法找到从相关元组列表构建树路径的方法 我只想要每个节点被访问一次的每个路径的列表 也称为哈密尔顿路径 我不断接近 但错过了一些路径 例如 假设我们有以下连接列表 connections 1 4 1 5 2 5 3 4 4 1 4 3 4
  • expo-auth-session - 返回应用程序时的两个应用程序选项

    SDK版本 43 0 0 平台 Android iOS 网络 所有 Android 您好 我在托管工作流程中使用 expo auth session 通过其官方 API 收集 Instagram 用户数据 它在开发环境中运行良好 通过 ex
  • awk 搜索字符串并设置退出代码(如果存在)

    我想检查两个地址之间是否存在一行并返回退出代码0如果它存在并且1如果没有 我想我已经有了一个可能的例子 但我想知道是否有一种更干净的方法来做到这一点 或者也许是 RedHat 上也常见的不同工具 我的命令 awk BEGIN found 1
  • 管道超级代理响应到快速响应

    我正在尝试使用 Express 应用程序 代理 一些文件 为什么下面的代码不起作用 var app require express var request require superagent app get image function
  • GeoServer 不会写入我的 PostgreSQL 可更新视图

    继从这个先前的问题我使用的是 PostgreSQL 8 4 并且在可更新视图方面遇到问题 我有一个看法 CREATE VIEW filedata view AS SELECT num id ST TRANSFORM the geom 900
  • 单击 vue 组件中的“保存”按钮后如何关闭模式?

    我的 vue 组件是这样的
  • Java listjar 目录中的文件

    有什么办法可以使用吗listFiles 在已打包到 jar 中的目录上 假设我的资源目录中有一个目录 其中包含一些文本文件 texts text1 txt and texts text2 txt 在这个 Java 程序中 我有一个需要使用的
  • 正确使用GetRawInputBuffer

    我正在尝试使用 Win32 原始输入 API 以更高精度收集原始鼠标数据 但我似乎无法理解文档和样本完全为了GetRawInputBuffer 当我的鼠标悬停在窗口上时 似乎什么也没有发生 当我单击或释放窗口标题栏时 我似乎只获得缓冲数据