Situation:
Today I am trying to optimize my remote control, and I need to use SendInput, which is in the class library, to move the mouse from one place to another continuously. However, I found that if you use SendInput in a loop in C#, the behavior becomes unexpected (what originally moved to the right will move upward, and the moving distance is also random).
What I have tried:
- I tried to use my
Simulateclass without looping, but there is nothing wrong if I just use it to move my mouse to a target place. - I tried to trace the code but I can not find anything wrong.
Envirement:
- Windows 11 family
- VS2022 community
- .NET Framework class library (4.8)
Code:
Normal case:
int CursorX = Cursor.Position.X;
int CursorY = Cursor.Position.Y;
for (int i = 0; i < 100; i++)
{
Simulator.MouseSimulator.MoveMouse((ushort)(CursorX + i), (ushort)(CursorY ), SCREENWIDTH, SCREENHEIGHT);
Thread.Sleep(2);
}
In this case, it will work.
Unexpected case:
for (int i = 0; i < 100; i++)
{
int CursorX = Cursor.Position.X;
int CursorY = Cursor.Position.Y;
Simulator.MouseSimulator.MoveMouse((ushort)(CursorX + MOVESPACE), (ushort)(CursorY ), SCREENWIDTH, SCREENHEIGHT);
Thread.Sleep(2);
}
In this case, the mouse will move top and move less than 100px on my computer.
Class code (just library to call SendInput API):
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
using static System.Collections.Specialized.BitVector32;
namespace Simulator
{
public static class MouseSimulator
{
[DllImport("user32.dll", SetLastError = true)]
public static extern uint SendInput(uint nInputs, INPUT[] pInputs, int cbSize);
private const double LEN = 65536;
public static uint MoveMouse(ushort x, ushort y, int screenWidth, int screenHeight, uint recordTime = 0, IntPtr additionalInfo = default(IntPtr))
{
MOUSEINPUT mouseInput = new MOUSEINPUT();
mouseInput.dx = (int)(x * (LEN / screenWidth));
mouseInput.dy = (int)(y * (LEN / screenHeight));
mouseInput.dwFlags = (uint)(MouseEventFlags.ABSOLUTE | MouseEventFlags.MOVE);
mouseInput.time = recordTime;
mouseInput.dwExtraInfo = additionalInfo;
InputUnion union = new InputUnion();
union.mi = mouseInput;
INPUT[] input = new INPUT[1];
input[0].type = (uint)InputTypes.MOUSE;
input[0].U = union;
return SendInput(1, input, Marshal.SizeOf(typeof(INPUT)));
}
public static uint SimulateMouse(MouseEventFlags action, uint mouseData = 0, uint recordTime = 0, IntPtr additionalInfo = default(IntPtr))
{
MOUSEINPUT mouseInput = new MOUSEINPUT();
//if (x != -1) mouseInput.dx = (int)(x * (65535F / screenWidth));
//if (y != -1) mouseInput.dy = (int)(y * (65535F / screenHeight));
mouseInput.mouseData = mouseData;
mouseInput.dwFlags = (uint)(MouseEventFlags.ABSOLUTE | action);
mouseInput.time = recordTime;
mouseInput.dwExtraInfo = additionalInfo;
InputUnion union = new InputUnion();
union.mi = mouseInput;
INPUT[] input = new INPUT[1];
input[0].type = (uint)InputTypes.MOUSE;
input[0].U = union;
return SendInput(1, input, Marshal.SizeOf(typeof(INPUT)));
}
}
public enum InputTypes : uint
{
MOUSE = 0,
KEYBOARD = 1,
HARDWARE = 2
}
public enum MouseEventFlags : uint
{
ABSOLUTE = 0x8000,
LEFTDOWN = 0x0002,
LEFTUP = 0x0004,
MIDDLEDOWN = 0x0020,
MIDDLEUP = 0x0040,
MOVE = 0x0001,
RIGHTDOWN = 0x0008,
RIGHTUP = 0x0010,
WHEEL = 0x0800,
XDOWN = 0x0080,
XUP = 0x0100,
HWHEEL = 0x01000
}
public enum KeyEventFlags : ushort
{
KEYDOWN = 0x0000,
EXTENDEDKEY = 0x0001,
KEYUP = 0x0002,
UNICODE = 0x0004,
SCANCODE = 0x0008
}
[StructLayout(LayoutKind.Sequential)]
public struct INPUT
{
public uint type;
public InputUnion U;
}
[StructLayout(LayoutKind.Explicit)]
public struct InputUnion
{
[FieldOffset(0)]
public MOUSEINPUT mi;
[FieldOffset(0)]
public KEYBDINPUT ki;
[FieldOffset(0)]
public HARDWAREINPUT hi;
}
[StructLayout(LayoutKind.Sequential)]
public struct MOUSEINPUT
{
public int dx;
public int dy;
public uint mouseData;
public uint dwFlags;
public uint time;
public IntPtr dwExtraInfo;
}
[StructLayout(LayoutKind.Sequential)]
public struct KEYBDINPUT
{
public ushort wVk;
public ushort wScan;
public uint dwFlags;
public uint time;
public IntPtr dwExtraInfo;
}
[StructLayout(LayoutKind.Sequential)]
public struct HARDWAREINPUT
{
public uint uMsg;
public ushort wParamL;
public ushort wParamH;
}
}
What I want:
I want to know why this situation will happen and how to solve it.