【问题标题】:c++ winapi SendInput unexpected behaviorc++ winapi SendInput 意外行为
【发布时间】:2017-11-16 21:04:03
【问题描述】:

我有以下代码,使用 Visual C++ 编译器编译

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

using namespace std;

int main() {
    SetProcessDPIAware();

    POINT p;
    GetCursorPos(&p);
    cout << p.x << " " << p.y << endl;

    int screenWidth = GetSystemMetrics(SM_CXSCREEN);
    int screenHeight = GetSystemMetrics(SM_CYSCREEN);

    INPUT in;
    in.type = INPUT_MOUSE;
    in.mi = {
        screenWidth / 2,
        screenHeight / 2,
        0,
        MOUSEEVENTF_MOVE,
        0,
        NULL
    };

    SendInput(1, &in, sizeof(in));

    GetCursorPos(&p);
    cout << p.x << " " << p.y << endl;

    return 0;
}

我的显示器是 1920x1080。从doc看来,如果我使用相对运动(在这种情况下我就是这样),dx 和 dy 应该是像素差。

当我运行此代码时,我将光标放在显示屏的左上角,我希望它最终会在中心,但它最终会在 (1243, 699) 处,远远超过中心。不知道为什么。

2 cout 的准确读数是

0 0
1243 699

【问题讨论】:

  • DPI 虚拟化是原因
  • @DavidHeffernan 你能详细说明一下吗?我是一个真正的新手,我找不到任何关于 DPI 虚拟化对鼠标事件的影响的文档。
  • 只是不要硬编码 960 和 540。调用 GetSystemMetrics() 获取屏幕大小,除以 2 以使鼠标居中。现在,您编写的 dpiAware 代码可以在任何机器上运行,无论屏幕大小以及 DPI 虚拟化是打开还是关闭。
  • @HansPassant 我向 GetSystemMetrics 查询了屏幕宽度和高度,它们确实是 1920x1080。我将代码更改为 width/2 和 height/2 但没有运气,它仍然以 1243,699 结束
  • @ShawnLi:你的坐标膨胀了~1.29%。看起来像 DPI 缩放给我。在 MSDN 的 Mouse MovementDPI and Device-Independant Pixels 文档中了解 DPI 对鼠标的影响。例如,120 的 DPI 设置使用大小为 1.25 像素的 DIP。嗯...您的应用中是否有 DPI 感知清单,或者使用 SetProcessDpiAware()/SetProcessDpiAwareness()?如果没有,请尝试添加。

标签: c++ winapi mouseevent


【解决方案1】:

使用MOUSEEVENTF_ABSOLUTE 标志并将点转换为鼠标坐标(00xFFFF)来设置鼠标坐标。否则 x/y 坐标被视为相对位置。

mouse_event

如果指定了MOUSEEVENTF_ABSOLUTE 值,则dx 和dy 包含 065,535 之间的标准化绝对坐标。事件 过程将这些坐标映射到显示表面上。协调 (0,0) 映射到显示表面的左上角, (65535,65535) 映射到右下角。

如果未指定MOUSEEVENTF_ABSOLUTE 值,则dxdy 指定 上次鼠标事件产生时的相对运动( 最后报告的位置)。正值表示鼠标向右移动 (或向下);负值表示鼠标向左(或向上)移动。

相对鼠标运动受鼠标速度和 加速水平。最终用户使用鼠标设置这些值 控制面板中的应用程序。应用程序获取并设置这些 SystemParametersInfo 函数的值...

SendInput中的第二个参数使用数组

int main() 
{
    SetProcessDPIAware();

    POINT p;
    GetCursorPos(&p);
    cout << p.x << " " << p.y << endl;

    int screenWidth = GetSystemMetrics(SM_CXSCREEN);
    int screenHeight = GetSystemMetrics(SM_CYSCREEN);
    cout << screenWidth << " " << screenHeight << endl;

    p.x = screenWidth / 2;
    p.y = screenHeight / 2;

    INPUT in[1] = { 0 };
    in[0].type = INPUT_MOUSE;
    in[0].mi.dx = (p.x * 0xFFFF) / (GetSystemMetrics(SM_CXSCREEN) - 1);
    in[0].mi.dy = (p.y * 0xFFFF) / (GetSystemMetrics(SM_CYSCREEN) - 1);
    in[0].mi.dwFlags = MOUSEEVENTF_ABSOLUTE | MOUSEEVENTF_MOVE;

    SendInput(1, in, sizeof(INPUT));

    GetCursorPos(&p);
    cout << p.x << " " << p.y << endl;

    return 0;
}

【讨论】:

  • 是的,使用绝对标志肯定会给我预期的结果。但是,是否有任何原因导致相对鼠标移动无法按预期工作?
  • 我原以为它会在中心结束您似乎不了解文档,或者您不了解“相对”和“相对”的含义运动”。 screenWidth / 2 不会以相对运动结束在中心,除非初始位置在 0, 0。在您的代码中明确指出您打算使用精确的屏幕坐标。
  • 从我的输出中可以看出。我的光标在 SendInput 之前位于 0,0
  • 查看相对位置的文档“鼠标的相对运动取决于鼠标速度和加速度级别的设置” ...
  • 啊,是的,鼠标速度和加速度水平是原因
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-04-09
  • 1970-01-01
  • 2017-05-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多