原始输入法中的鼠标位置

问题描述 投票:0回答:2

我正在尝试使用原始输入法获取鼠标位置。在 RAWMOUSE 结构中,我总是获取 MOUSE_MOVE_RELATIVE 作为 usFlags 值,这意味着我获取最后鼠标位置的相对值。但我想要鼠标的绝对位置。如何从原始输入中获取鼠标的绝对位置值?

mouse mouseevent raw-input
2个回答
3
投票

[很奇怪看到一个 9 年前未解答的问题成为 google 搜索结果的热门,所以我会提供一个答案..迟做总比不做好!]

在原始输入 API 级别,您将获得鼠标设备的原始水平/垂直移动——鼠标在硬件级别报告的内容。

根据文档(我尚未验证),这些增量 X/Y 值尚未由桌面鼠标速度/加速/减速设置处理。因此,即使您从已知的绝对位置开始跟踪增量,您也会很快偏离 Windows 在屏幕上定位鼠标光标的位置。

文档中不清楚的是报告这些相对 X/Y 值的单位或比例。如果能以某种方式标准化那就太好了,但我怀疑这取决于鼠标的 DPI 分辨率。 (我会找一个可调节 DPI 的鼠标来测试,如果没有人先编辑我,我会报告回来。)

编辑/更新:我拿到了具有可调节 DPI 的鼠标..做了一些粗略的测试,足以确认 lLastX/Y 值的粗略比例似乎与硬件 DPI 相匹配..例如。鼠标处于 1200 dpi 模式时,从左向右物理移动 1 英寸,生成 lLastX 值的净和 ~= 1200。


2
投票

RAWMOUSE
具有与 Windows 从鼠标硬件接收的完全相同的值(可能是 HID USB/蓝牙或 i8042 PS/2 鼠标等)。通常鼠标发送相对移动,但有些可以发送绝对移动 - 例如触摸屏、RDP 鼠标(耶!)。

因此,如果您需要绝对鼠标位置(例如游戏菜单),您可以使用 GetCursorPos API 来获取 Windows 渲染的光标在屏幕上的坐标。

但它与

MOUSE_MOVE_ABSOLUTE
中带有
RAWMOUSE
标志发送的内容不同。

MOUSE_MOVE_ABSOLUTE
是设备空间(而不是屏幕空间)中 0..65535 范围内的鼠标移动。这是一些如何将其转换为屏幕空间的代码:

if (raw->mouse.usFlags & MOUSE_MOVE_ABSOLUTE)
{
    RECT rect;
    if (raw->mouse.usFlags & MOUSE_VIRTUAL_DESKTOP)
    {
        rect.left = GetSystemMetrics(SM_XVIRTUALSCREEN);
        rect.top = GetSystemMetrics(SM_YVIRTUALSCREEN);
        rect.right = GetSystemMetrics(SM_CXVIRTUALSCREEN);
        rect.bottom = GetSystemMetrics(SM_CYVIRTUALSCREEN);
    }
    else
    {
        rect.left = 0;
        rect.top = 0;
        rect.right = GetSystemMetrics(SM_CXSCREEN);
        rect.bottom = GetSystemMetrics(SM_CYSCREEN);
    }

    int absoluteX = MulDiv(raw->mouse.lLastX, rect.right, 65535) + rect.left;
    int absoluteY = MulDiv(raw->mouse.lLastY, rect.bottom, 65535) + rect.top;
    ...
}
else if (raw->mouse.lLastX != 0 || raw->mouse.lLastY != 0)
{
    int relativeX = raw->mouse.lLastX;
    int relativeY = raw->mouse.lLastY;
    ...
}
© www.soinside.com 2019 - 2024. All rights reserved.