I'm trying to simulate mouse input using SendInput
, however I need to determine the virtual screen width in case there are multiple monitors, to set the dx
and dy
values, for example:
dx = (x * 65536) / SystemInformation.VirtualScreen.Width;
dy = (y * 65536) / SystemInformation.VirtualScreen.Height;
The problem is that the monitors apparently have different DPI values, which results in an incorrect virtual size.
For reference, both SystemInformation.VirtualScreen.Size
and calls to GetSystemMetrics(SM_CXVIRTUALSCREEN)
return the same incorrect values.
I tried using GetSystemMetricsForDPI
with no success either.
By default, Windows applies DPI virtualization to all coordinates.
If you have 2 displays, secondary FullHD on the left with 100% scaling, and primary 4k on the right with 200% DPI scaling, the APIs for screen configuration gonna tell you the desktop has 3840x1080 pixels, the secondary one from [-1920 .. 0], the primary one [0 .. 1920]. To simulate mouse input at the center of the left monitor, you should use X coordinate -960 * 0x10000 / 1920 = -32768 without MOUSEEVENTF_VIRTUALDESK
flag, or 960 * 0x10000 / 3840 = 16384 with MOUSEEVENTF_VIRTUALDESK
flag
You can tell Windows to stop messing with DPI in your application, with a manifest.
If you do that on the same computer, the APIs for screen configuration gonna tell you the desktop has 5760x2160 pixels, the secondary one is the same, in [-1920 .. 0 ], the primary one [ 0 .. 3840 ]. To send mouse input to the center of the left monitor in this case, you should use X coordinate -960 * 0x10000 / 3840 = -16384 without MOUSEEVENTF_VIRTUALDESK
flag, or 960 * 0x10000 / 5760 = 10923 with MOUSEEVENTF_VIRTUALDESK
flag.