Есть программа на C#, она с некоторыми промежутками времени кликает по окну. Буквально 3 дня назад все работало, с тех пор код не меняла, но кликать стал как-то странно.
public static void clickLeftOnPoint(Point point)
{
if (!point.IsEmpty)
{
int x = Convert.ToInt32(point.X / 1.25);
int y = Convert.ToInt32(point.Y / 1.25);
Point offsetPoint = new Point(x + 5, y + 5);
WinApi.mouseClickLeft(offsetPoint.X, offsetPoint.Y);
Wait();
}
}
public static void mouseClickLeft(int x, int y)
{
IntPtr hwnd = getWindow();
SetForegroundWindow(hwnd);
ShowWindow(hwnd, 1);
UserHelper.Wait();
ClickLeftMouseButton(hwnd, x, y);
}
public static void ClickLeftMouseButton(IntPtr hwnd, int x, int y)
{
x = CalculateAbsoluteCoordinateX(x);
y = CalculateAbsoluteCoordinateY(y);
INPUT[] inputs = new INPUT[3];
inputs[0] = new INPUT
{
type = SendInputEventType.InputMouse,
mkhi = new MouseKeybdhardwareInputUnion
{
mi = new MouseInputData
{
dx = x,
dy = y,
mouseData = 0,
dwFlags = MouseEventFlags.MOUSEEVENTF_MOVE | MouseEventFlags.MOUSEEVENTF_ABSOLUTE
}
}
};
inputs[1] = new INPUT
{
type = SendInputEventType.InputMouse,
mkhi = new MouseKeybdhardwareInputUnion
{
mi = new MouseInputData
{
dx = x,
dy = y,
mouseData = 0,
dwFlags = MouseEventFlags.MOUSEEVENTF_LEFTDOWN | MouseEventFlags.MOUSEEVENTF_LEFTUP
}
}
};
var result = SendInput((uint)inputs.Length, inputs, Marshal.SizeOf(typeof(INPUT)));
Console.WriteLine("Result: " + result);
}
В некоторые места клик проходит и я вижу сообщения (предварительно активирую окно):

Дальше начинается самое странное (отправляется сообщение WM_SETCURSOR, а сообщения кликов - нет):

Не сильна в WinApi, не особо понимаю, почему недавно работало, а теперь перестало. Пробовала использовать другие способы клика, но там вообще сообщения в окно не проходят.
Создается впечатление, что первый клик проходит всегда, а последующие как будто блокируются, визуально окно остается активным, но сообщения на клики игнорятся
Marshal.SizeOf(new INPUT())замените наMarshal.SizeOf(typeof(INPUT))илиMarshal.SizeOf<INPUT>(), вот пример, возможно поможет. – aepot Jun 10 '22 at 19:25SendInputможет принимать массив инпутов, а не один инпут. Попробуйте передать свою группу на ввод пачкой, а не по одному. – aepot Jun 10 '22 at 19:35IntPtr hwnd = getWindow(); SetForegroundWindow(hwnd); ShowWindow(hwnd, 1); Thread.Sleep(1000); Дальше вызываю метод клика, передаю туда корды. Снова запускается таймер, и так по кругу. – Neonika Jun 10 '22 at 21:28
Thread.Sleepв UI потоке делать нельзя, совсем нельзя, это очень плохо, замените наawait Task.Delay, если уж очень надо. 1) Уберите таймер, переделайте на асинхронный цикл. 2) как я показал выше, передавайте все события мыши разом одним массивом, оно пачкой отработает нормально, при этом вы снизите нагрузку на WinAPI в 3 раза. 3) Если я прав про проблемы с UI потоком, теоретически запуск кликера от имени администратора должен убрать симптомы, но это конечно же не решение, у админских приложений своя очередь в WM Loop. – aepot Jun 10 '22 at 22:03UserHelper.Wait();иWait();случаем неThread.Sleep? :) везде оно у вас.MouseEventFlags.MOUSEEVENTF_LEFTDOWN | MouseEventFlags.MOUSEEVENTF_LEFTUPтак делать нельзя, отдельно DOWN, отдельно UP надо в массив ложить. – aepot Jun 10 '22 at 22:07new INPUT[3]создаете, а добавляете 2.mouseData = 0можно не присваивать, оно и так 0 по умолчанию. – aepot Jun 10 '22 at 22:08