使用Input Simulator模拟键盘与鼠标的输入 (.NET C sharp)

3,658 阅读3分钟

InputSimulator

InputSimulator之前,模拟键盘与鼠标的操作是非常痛苦的,如果我们想按下一个ctrl键:

[DllImport("user32.dll", SetLastError = true)]
static extern void KEYBD_EVENT(byte bVk, byte bScan, int dwFlags, int dwExtraInfo); 
public const int KEYEVENTF_EXTENDEDKEY = 0x0001;
public const int KEYEVENTF_KEYUP = 0x0002;
public const int VK_RCONTROL = 0xA3;
KEYBD_EVENT(VK_RCONTROL, 0, KEYEVENTF_EXTENDEDKEY, 0);
KEYBD_EVENT(VK_RCONTROL, 0, KEYEVENTF_KEYUP, 0); 

这看起来有点汇编的味道,我们需要频繁的查阅MSDN [docs.microsoft.com/zh-cn/windo…],最后甚至定义了上百行const int,在Win Form中,我们可以使用SendKeys,它的参数非常古怪,看起来像是制作了一种专用的DSL,而且很多情况下它是无效的,不能模拟出实际的键盘操作,如果你不喜欢这两种方式,那么你应该使用InputSimulator

InputSimulator提供了一个简单的.NET C#键盘输入接口,使用Win32 SendInput方法模拟键盘或鼠标的标输入,可以同时触发多个键或鼠标,也可以输入文本,模拟剪切板操作,鼠标左右键点击,可以在NuGet中下载安装InputSimulator,或者在Github中clone它。

InputSimulator的操作非常简单,所有的基础操作都封装在InputSimulator中。

例如按下A键

InputSimulator.SimulateKeyPress(VirtualKeyCode.VK_A);

为了兼容更多的应用程序,InputSimulatorPlus诞生了,它的使用方式和InputSimulator别无二致。在InputSimulatorPlus的基础上,又出现了InputSimulatorStandard,它支持.Net Standard,去掉了InputSimulator中的静态方法,如上面的例子中,应该这样写:

var simulator = new InputSimulator();
simulator.Keyboard.KeyPress(VirtualKeyCode.VK_A);

显然在更多的情况下,这是一种较好的方式

下面粗略介绍一些用例,我默认已经定义了 var simulator = new InputSimulator();

通常我们需要按下组合键,使用ModifiedKeyStroke是最简便的,它能模拟复制与粘贴

simulator.Keyboard.ModifiedKeyStroke(VirtualKeyCode.CONTROL, VirtualKeyCode.VK_C);
simulator.Keyboard.ModifiedKeyStroke(VirtualKeyCode.CONTROL, VirtualKeyCode.VK_V);

按住shift键的时候,按下其他字母键,输入的字母会变成大写,运行下面的用例,会输入文本"ABC"

simulator.Keyboard.SimulateKeyDown(VirtualKeyCode.SHIFT);//按下shift
simulator.Keyboard.SimulateKeyPress(VirtualKeyCode.VK_A);//输入a
simulator.Keyboard.SimulateKeyPress(VirtualKeyCode.VK_B);
simulator.Keyboard.SimulateKeyPress(VirtualKeyCode.VK_C);
simulator.Keyboard.SimulateKeyUp(VirtualKeyCode.SHIFT);//释放shift

当然有更简便的方法,使用方法TextEntry直接输入ABC

simulator.Keyboard.TextEntry("ABC");

直接使用simulator.Keyboard.SimulateKeyPress(VirtualKeyCode.VK_A);时,你可能不知道自己输入了大写的A还是小写的a,这时候首先想到要去检测一个键是否处于被按下的状态,例如shift键

bool isShiftKeyDown = simulator.InputDeviceState.IsKeyDown(VirtualKeyCode.SHIFT);

但是它对大小写是否开启的判断是无效的,下面的代码就无法检测出当前的键盘状态是处于大写还是小写

bool isCapsLockOn = simulator.InputDeviceState.IsKeyDown(VirtualKeyCode.CAPITAL);

原因很简单,Caps Lock键不像shift,ctrl,alt一类的控制键,需要持续的按下。它只需要按下一次,就会开启。那么应该使用IsTogglingKeyInEffect,它可以检查一个切换键是否被启用,当然,除了Caps Lock,还有Scroll LockNum Lock

bool isCapsLockOn = simulator.InputDeviceState.IsTogglingKeyInEffect(VirtualKeyCode.CAPITAL);

鼠标的操作也非常简便

左键单击,右键双击

simulator.Mouse.LeftButtonClick();
simulator.Mouse.RightButtonDoubleClick();

向上垂直滚动一格,向下垂直滚动两格

simulator.Mouse.VerticalScroll(1);
simulator.Mouse.VerticalScroll(-2);

想移动鼠标到指定位置则比较复杂,你需要先获取屏幕大小,你可以使用SystemParameters来获取当前主屏的屏幕大小

var screenHeight = SystemParameters.PrimaryScreenHeight;
var screenWidth = SystemParameters.PrimaryScreenWidth;

也可以获取到所有屏幕的全屏大小

var screenHeight = SystemParameters.FullPrimaryScreenHeight;
var screenWidth = SystemParameters.FullPrimaryScreenWidth;

如果你在Win Form中,也可以使用System.Windows.Forms.Screen获取主屏的大小

int screenWidth = Screen.PrimaryScreen.Bounds.Width;
int screenHeight = Screen.PrimaryScreen.Bounds.Height;

全屏大小则需要通过Screen中的AllScreensBounds自行计算,过程较为复杂

获取到屏幕大小之后,我们将坐标(30,50)进行计算,获取到屏幕中的绝对位置

int X = 30 * 0xffff / screenWidth;
int Y = 50 * 0xffff / screenHeight;

然后转换为double,代入MoveMouseToPositionOnVirtualDesktop,操作就完成了

simulator.Mouse.MoveMouseToPositionOnVirtualDesktop(Convert.ToDouble(X), Convert.ToDouble(Y));

具体的用例除了NuGet与Github的主页面中有介绍外,在下面的一些文章中也有介绍它