Leo
Leo

Reputation: 418

SendInput always moves mouse pointer to left top corner

I would like to programmatically synthesize mouse motion to a point (100,100) on a screen with code below, but it moves to left top side instead. What could be wrong?

#include "stdafx.h"
#include<Windows.h>

int main() {
  INPUT input;
  input.type = INPUT_MOUSE;
  input.mi.dx = 100;
  input.mi.dy = 100;
  input.mi.dwFlags = MOUSEEVENTF_ABSOLUTE | MOUSEEVENTF_MOVE;
  input.mi.mouseData = 0;
  input.mi.dwExtraInfo = NULL;
  input.mi.time = 0;
  SendInput(1, &input, sizeof(INPUT));
  return 0;
}

PS. I have compiled it in VS2017 on Windows 10x64. I have run the code on Win7 as well

PPS. When I remove MOUSEEVENTF_ABSOLUTE flag, it moves to relative position.

Upvotes: 4

Views: 1637

Answers (1)

IInspectable
IInspectable

Reputation: 51412

The API call follows documented behavior:

MOUSEEVENTF_ABSOLUTE: The dx and dy members contain normalized absolute coordinates. [...] see the following Remarks section.

Normalized coordinates are indeed described in the Remarks section:

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; coordinate (65535,65535) maps onto the lower-right corner. In a multimonitor system, the coordinates map to the primary monitor.

To move the mouse to an absolute position, you first need to query the display surface size (e.g. through a call to GetMonitorInfor), and scale the coordinates appropriately.

The following function normalizes a point, given the point and display surface dimensions in device units as input:

POINT normalize(POINT const& pt_in_px, RECT const& display_size_in_px)
{
    POINT pt_normalized{};

    auto const width_in_px{ display_size_in_px.right - display_size_in_px.left };
    auto const height_in_px{ display_size_in_px.bottom - display_size_in_px.top };

    pt_normalized.x = ::MulDiv(pt_in_px.x, 65536, width_in_px);
    pt_normalized.y = ::MulDiv(pt_in_px.y, 65536, height_in_px);

    return pt_normalized;
}

Upvotes: 7

Related Questions