如何准确测量具有已知 DPI 的鼠标的鼠标移动(以英寸或厘米为单位)

2023-12-15

我有一个 Logitech G500 游戏鼠标,其全 DPI 为 5700。

我正在尝试用 C++ 编写一个程序,以物理单位准确测量鼠标的水平移动,即。厘米或英寸。

我通过 WM_INPUT 消息使用 Windows API 和 Windows 原始输入来获取鼠标的原始移动变化。

然后,我假设通过 WM_INPUT 报告的 1 个移动单位是 1/5700 英寸,并且当我跟踪鼠标的净移动时,我认为我可以执行一个简单的计算来产生净物理移动:

距离(英寸)=total_movement_from_wminput / dpi; // 在本例中 dpi = 5700

不幸的是,计算似乎并不准确。我可以从鼠标垫上的物理测量得知,鼠标移动约 6 英寸后,计算得出的值约为 5 英寸半(损失约 1/2 英寸)。

我哪里错了?我在控制面板中将鼠标设置为5700DPI,它的实际DPI会比这个小吗?我关于通过 WM_INPUT 的 1 个单位的变化是 1/dpi 英寸物理运动的假设是否正确?

有谁对我如何使其准确有任何想法吗?谢谢!


Marc,

看来问题可能是当你移动鼠标的速度比 Windows 事件快时WM_INPUT处理它。例如,假设鼠标在一帧中移动了 2 个像素。你会损失 1/5700 英寸(在你的情况下),因为对于one WM_INPUT事件已处理,您将移动two pixels.

要解决此问题,您应该检查有多少像素每次向程序发送 WM_INPUT 消息时,鼠标都会移动。你要做的就是做一个RAWINPUTDEVICE 变量并设置结构,使其包含有关鼠标的信息。

以下代码注册了RAWINPUTDEVICE所以它可以用在WM_INPUT.

RAWINPUTDEVICE Rid[1];
Rid[0].usUsagePage = HID_USAGE_PAGE_GENERIC;
Rid[0].usUsage = HID_USAGE_GENERIC_MOUSE; 
Rid[0].dwFlags = RIDEV_INPUTSINK;   
Rid[0].hwndTarget = hWnd;
RegisterRawInputDevices(Rid, 1, sizeof(Rid[0]);

下面的代码实际上使用了Rid变量二确定自上次以来鼠标移动了多少像素WM_INPUT被发起。

case WM_INPUT: 
{
    UINT dwSize = 40;
    static BYTE lpb[40];

    GetRawInputData((HRAWINPUT)lParam, RID_INPUT, 
                    lpb, &dwSize, sizeof(RAWINPUTHEADER));

    RAWINPUT* raw = (RAWINPUT*)lpb;

    if (raw->header.dwType == RIM_TYPEMOUSE) 
    {
        int xPosRelative = raw->data.mouse.lLastX; // Could be 1, or could be more than 1
        int yPosRelative = raw->data.mouse.lLastY; // Could be 1, or could be more than 1!
    } 
    break;
}

请注意,此代码与 msdn 上有关该主题的代码相同(链接如下)。

您现在可以拥有某种类型的全局变量,其中包含鼠标的 x 位置和 y 位置(以像素为单位)。然后,您只需将这些变量除以 DPI,就可以得到与将全局变量设置为 0 时的英寸偏移量。


总共一个easier方法是处理WM_MOUSEMOVE事件代替。它可以轻松获得鼠标的准确位置(当然以像素为单位)。使用它,您可以从起始位置的像素值中减去它。

Example:

分辨率 = 5700。

初始位置 = (100px, 300px)。

3 秒后的位置 = (500px, 400px)。

这 3 秒内移动的英寸数 = ( (500px - 100px)/5700 英寸, (400px - 300px)/5700 英寸 )

一般规则:S 秒后移动的英寸数 = (inital_pixels_x - Final_pixels_x)/DPI 英寸

水平方向,(initial_pixels_y - Final_pixels_y)/DPI 英寸,垂直方向

这里,final_pixels_x 是 s 秒后鼠标的 x 位置,final_pixels y 是 s 秒后的 y 位置。


总结一下你做错了什么,你错误地假设每个WM_INPUT事件意味着鼠标移动了 1 个像素。

如果我出于某种原因误解了这个问题,并且您知道您已经移动了正确数量的像素,请发表评论,我将尽力尝试修复我的答案。不过,我仍然建议使用WM_MOUSEMOVE代替WM_INPUT因为它是专门针对鼠标的,并且它应用“指针加速”,您可以在最底部的链接上阅读有关内容。

感谢您提出问题,tcs08

WM_INPUT鼠标输入的msdn代码和解释

WM_MOUSEMOVE鼠标输入的msdn代码和解释

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

如何准确测量具有已知 DPI 的鼠标的鼠标移动(以英寸或厘米为单位) 的相关文章

随机推荐

  • C# 等待用户在文本框中输入完毕

    C 中是否有一种方法可以等到用户在文本框中完成输入后再获取他们输入的值而不按 Enter 键 稍微修改一下这个问题 好吧 我有一个简单的乘以 2 的计算器 这是我想要它做的事情 用户在文本框中输入一个值 例如 1000 它会自动显示 200
  • R脚本从谷歌分析导入数据

    我正在尝试通过 R studio 服务器上运行的脚本连接到 google analytic s API 我已按照本教程中的步骤操作 http www r bloggers com how to extract google analytic
  • 将 && \ 添加到文本文件中除最后一行之外的每一行

    我正在尝试添加 在文本文件中除最后一行之外的每一行的末尾 输入示例 ps mkdir repo cd repo touch file1 txt 预期输出 ps mkdir repo cd repo touch file1 txt 第一次尝试
  • 如何在使用 QnA 机器人时对其进行训练?

    我使用 bot framework SDK3 和 QnAmaker 服务制作了一个 QnA 机器人 据我所知 我们可以训练我们的知识库 但我不知道如何在团队等其他渠道中使用我的 QnA 机器人时对其进行训练 我想我可以让用户判断机器人的回答
  • subprocess.call() 和 os.system() 之间的速度差异

    执行速度是否有任何差异subprocess call and os system 命令 假设命令本身完全相同 我知道有很多帖子谈论子流程的好处及其原因os system 应该被抛弃 但没有人提到它们的速度 据我了解 子流程远不及包装器os
  • JSON 序列化以元组为键的字典

    Python 有没有办法序列化使用元组作为键的字典 e g a 1 2 a 简单地使用json dumps a 引发此错误 Traceback most recent call last File
  • 将 firestore“integer_value”转换为整数

    使用 Golang Firestore 1 8 库 我尝试使用 Google 去年秋天推出的 Firestore 的新 count 函数 这些文档似乎还没有示例 不是我发现的 但我拼凑了一些有点可行的代码 这些代码几乎让我完成了所有工作 只
  • WPF 拖放

    如何为 WPF 应用程序实现拖放 我可以打开 2 个相同的应用程序并将一个对象从一个应用程序拖动到另一个应用程序 这是我要拖动的内容
  • 按行重塑数据框[重复]

    这个问题在这里已经有答案了 我有一个类似于以下示例的数据框 gt df lt data frame imp c Johny Johny Lisa Max item c 5025 1101 2057 1619 gt df imp item 1
  • 仅最初需要 git 子模块更新?

    我正在掌握 git 子模块 一厢情愿的想法 并且我提出了更具体的问题 这是一个好兆头 我试图找到超级项目引用的子模块的哪个版本 在 gitmodules and git config 但那里没有提到任何内容 这种情况是 我正在更改根位置的子
  • 与 HoloEverywhere 的相对 Gradle 项目依赖性

    我有这个目录结构 Project contrib holo everywhere library addons slider preferences app library app one app two settings gradle 我
  • 保留选定的打印机设置

    我有一个应用程序 它运行一系列预订 并以行程的形式依次打印每个预订并发送给客户 每次运行可能有 30 个左右的预订 因此需要自动化 我们已经交付了它 所有这些都可以与我们的报告软件 DELPHI 的 Report Builder 配合使用
  • 使用 / 分割 C++ 字符串

    我有一个 C 字符串 如下所示 dirname filename ini 我需要在之后得到一切 我怎样才能做到这一点 Using find and substr方法来自std string std string fullpath dirna
  • 模块构建失败(来自 ./node_modules/postcss-loader/src/index.js)

    当我运行命令时 我正在使用角度和节点npm start我收到这个错误 src styles scss 中的错误 node modules css loader dist cjs js ref 13 1 node modules postcs
  • 运算符重载,运算符+与运算符+=

    我正在阅读一些 C 源代码 并且了解了一些语法 path path operator string postPath 我想知道这是否是实际的语法以及为什么 c 不使用已经存在的运算符 而是将值应用于有问题的对象 就像您想确保对象被正确删除一
  • 按对象键过滤对象数组

    我有一个 Javascript 对象数组 var List employee Joe type holiday employee Jerry type seminar employee Joe type shore leave 我想获得两个
  • Rails 的地理定位 API [关闭]

    Closed 此问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 目前不接受答案 我试图从我的 Rails 应用程序中显示某个位置的地图 我尝试检查 YM4R GM 和 GeoKit 组合 但不确定是否有更好的 Rails 3 的
  • 转换为 64 位 int

    因此 我正在使用 PHP 来转换 Steam Id 这可能是你们很多人都熟悉的 我有以下 Steam ID STEAM 0 1 1514332 现在 我需要将其转换为 64 位版本 这也是社区 ID 浏览 Steams 官方发布后 http
  • 如何在 WPF 中过滤 ListView?

    我有一个绑定到项目集合的 ListView 我不想显示属性 IsDeleted 1 的项目 我怎样才能做到这一点 我将使用 CollectionView 并将 Filter 属性设置为表达式 var view CollectionViewS
  • 如何准确测量具有已知 DPI 的鼠标的鼠标移动(以英寸或厘米为单位)

    我有一个 Logitech G500 游戏鼠标 其全 DPI 为 5700 我正在尝试用 C 编写一个程序 以物理单位准确测量鼠标的水平移动 即 厘米或英寸 我通过 WM INPUT 消息使用 Windows API 和 Windows 原