c# Неожиданное поведение mouse_event MOVE
Есть тестовый проект, который просто перемещает мышь через mouse_event на 100 пикселей вперед и низ. Но координаты после выполнения этого метода получаются совсем не такими, как я ожидал. Помогите найти ошибку
Код:
using System;
using System.Runtime.InteropServices;
namespace mouse_move_test
{
class Program
{
const int ABSOLUTE = 0x00008000;
const int MOVE = 0x00000001;
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool GetCursorPos(out MousePoint lpMousePoint);
public static MousePoint GetCursorPosition()
{
MousePoint currentMousePoint;
var gotPoint = GetCursorPos(out currentMousePoint);
if (!gotPoint) { currentMousePoint = new MousePoint(0, 0); }
return currentMousePoint;
}
[DllImport("user32.dll")]
private static extern void mouse_event(int dwFlags, int dx, int dy, int dwData, int dwExtraInfo);
[StructLayout(LayoutKind.Sequential)]
public struct MousePoint
{
public int X;
public int Y;
public MousePoint(int x, int y)
{
X = x;
Y = y;
}
}
static void Main(string[] args)
{
int dt = 100;
// Тест относительных координат
Console.WriteLine($"Тест относительных координат");
for (int i = 0; i < 3; i++)
{
var pos = GetCursorPosition();
Console.WriteLine($"{pos.X} {pos.Y} - текущая позиция");
Console.WriteLine($"{pos.X + dt} {pos.Y + dt} - ожидание");
mouse_event(MOVE, dt, dt, 0, 0);
pos = GetCursorPosition();
Console.WriteLine($"{pos.X} {pos.Y} - реальность");
Console.WriteLine();
}
// Тест абсолютных координат
Console.WriteLine($"Тест абсолютных координат");
for (int i = 0; i < 3; i++)
{
var pos = GetCursorPosition();
Console.WriteLine($"{pos.X} {pos.Y} - текущая позиция");
Console.WriteLine($"{pos.X + dt} {pos.Y + dt} - ожидание");
mouse_event(MOVE | ABSOLUTE, pos.X + dt, pos.Y + dt, 0, 0);
pos = GetCursorPosition();
Console.WriteLine($"{pos.X} {pos.Y} - реальность");
Console.WriteLine();
}
Console.ReadLine();
}
}
}
Вывод в консоль:
Тест относительных координат
0 0 - текущая позиция
100 100 - ожидание
155 155 - реальность
155 155 - текущая позиция
255 255 - ожидание
409 409 - реальность
409 409 - текущая позиция
509 509 - ожидание
664 664 - реальность
Тест абсолютных координат
664 664 - текущая позиция
764 764 - ожидание
22 12 - реальность
22 12 - текущая позиция
122 112 - ожидание
3 1 - реальность
3 1 - текущая позиция
103 101 - ожидание
3 1 - реальность
upd. Я правда пытаюсь) Приложение WPF. Я постараюсь привести упрощенные методы, мб это поможет Есть хук мыши
private int MouseHookProc(int nCode, int wParam, IntPtr lParam)
{
if (nCode >= 0)
{
Console.WriteLine($"wParam {wParam}");
return CallNextHookEx(hMouseHook, nCode, wParam, lParam);
}
}
Если я вызываю код mouse_event(0x00000001, 100, 100, 0, 0); Я получаю в лог wParam 512 Если использую код SetCursorPos(100, 100); То ничего не перехватывается. Что касается SendMessage с ним у меня были какие-то проблемы. Кажется, не работает в играх
dpi у меня 96, как я выяснил. А у координат прирост 50%. Где-то есть масштаб 150% который я пока не знаю как достать
Ответы (1 шт):
Итак, проблему удалось решить через флаг абсолютных координат, хотя поведения без него с непропорциональными коэффициентами я так и не раскусил. Информацию нашел сначала тут https://stackoverflow.com/questions/62626388/c-sharp-winapi-mouse-event потом уже и в справке https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-mouse_event в ремарке. Кстати там же есть что-то полезное и про относительные координаты (без флага), но я уже не мог. Имея рабочий вариант с абсолютными координатами уже не проблема использовать его и для относительных.
using System;
using System.Runtime.InteropServices;
namespace mouse_move_test
{
class Program
{
const int ABSOLUTE = 0x00008000;
const int MOVE = 0x00000001;
[DllImport("user32.dll")]
static extern int GetSystemMetrics(int nIndex);
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool GetCursorPos(out MousePoint lpMousePoint);
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool SetCursorPos(int x, int y);
public static MousePoint GetCursorPosition()
{
MousePoint currentMousePoint;
var gotPoint = GetCursorPos(out currentMousePoint);
if (!gotPoint) { currentMousePoint = new MousePoint(0, 0); }
return currentMousePoint;
}
[DllImport("user32.dll")]
private static extern void mouse_event(int dwFlags, int dx, int dy, int dwData, int dwExtraInfo);
[StructLayout(LayoutKind.Sequential)]
public struct MousePoint
{
public int X;
public int Y;
public MousePoint(int x, int y)
{
X = x;
Y = y;
}
}
static void Main(string[] args)
{
int dt = 100;
// получаем разрешение экрана
int sx = GetSystemMetrics(0);
int sy = GetSystemMetrics(1);
// Тест относительных координат
Console.WriteLine($"Тест абсолютных координат");
for (int i = 0; i < 3; i++)
{
SetCursorPos(0, 0);
var pos = GetCursorPosition();
Console.WriteLine($"{pos.X} {pos.Y} - текущая позиция");
Console.WriteLine($"{pos.X + dt} {pos.Y + dt} - ожидание");
int x = (int)Math.Ceiling(65536d / sx * dt);
int y = (int)Math.Ceiling(65536d / sy * dt);
mouse_event(MOVE | ABSOLUTE, x, y, 0, 0);
pos = GetCursorPosition();
Console.WriteLine($"{pos.X} {pos.Y} - реальность");
Console.WriteLine();
dt += 100;
}
Console.ReadLine();
}
}
}
Вывод
Тест абсолютных координат
0 0 - текущая позиция
100 100 - ожидание
100 100 - реальность
0 0 - текущая позиция
200 200 - ожидание
200 200 - реальность
0 0 - текущая позиция
300 300 - ожидание
300 300 - реальность