Shawn Li
Shawn Li

Reputation: 417

c++ winapi SendInput unexpected behavior

I have the following code, compiled using Visual C++ compiler

#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;
}

My display is 1920x1080. From the doc, it seems that if I use relative movement (which I am in this case), dx and dy should be the difference in pixels.

When I ran this code, I placed my cursor at the top-left corner of my display and I was expecting it to end up at the center, however it ended up at (1243, 699), way past the center. Couldn't figure out why.

The exact reading of the 2 cout are

0 0
1243 699

Upvotes: 0

Views: 635

Answers (1)

Barmak Shemirani
Barmak Shemirani

Reputation: 31669

Use MOUSEEVENTF_ABSOLUTE flag and convert the points to mouse coordinates (0 to 0xFFFF) to set the mouse coordinates. Otherwise the x/y coordinates are regarded as relative positions.

mouse_event

If MOUSEEVENTF_ABSOLUTE value is specified, dx and dy contain normalized absolute coordinates between 0 and 65,535. The event procedure maps these coordinates onto the display surface. Coordinate (0,0) maps onto the upper-left corner of the display surface, (65535,65535) maps onto the lower-right corner.

If the MOUSEEVENTF_ABSOLUTE value is not specified, dx and dy specify relative motions from when the last mouse event was generated (the last reported position). Positive values mean the mouse moved right (or down); negative values mean the mouse moved left (or up).

Relative mouse motion is subject to the settings for mouse speed and acceleration level. An end user sets these values using the Mouse application in Control Panel. An application obtains and sets these values with the SystemParametersInfo function...

Use an array for the second parameter in 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;
}

Upvotes: 1

Related Questions