using anjianjingling.Common; using anjianjingling.Native; using System.Runtime.InteropServices; namespace anjianjingling.Input { /// /// 系统级键盘模拟(SendInput):单键、组合键、Unicode 文本。 /// public sealed class KeyboardInput { private static void SendKey(Win32.KEYBDINPUT ki) { var input = new Win32.INPUT { type = Win32.INPUT_KEYBOARD, u = new Win32.INPUTUNION { ki = ki } }; Win32.SendInput(1, new[] { input }, Marshal.SizeOf()); } /// 发送一次按键(按下并弹起)。 public void KeyPress(string keyName) { ushort vk = ResolveOrThrow(keyName); KeyDownVk(vk); Thread.Sleep(30); KeyUpVk(vk); } public void KeyDown(string keyName) => KeyDownVk(ResolveOrThrow(keyName)); public void KeyUp(string keyName) => KeyUpVk(ResolveOrThrow(keyName)); private static void KeyDownVk(ushort vk) { ushort scan = (ushort)Win32.MapVirtualKey(vk, Win32.MAPVK_VK_TO_VSC); uint flags = Win32.KEYEVENTF_SCANCODE; if (VirtualKeys.IsExtended(vk)) flags |= Win32.KEYEVENTF_EXTENDEDKEY; SendKey(new Win32.KEYBDINPUT { wVk = vk, wScan = scan, dwFlags = flags }); } private static void KeyUpVk(ushort vk) { ushort scan = (ushort)Win32.MapVirtualKey(vk, Win32.MAPVK_VK_TO_VSC); uint flags = Win32.KEYEVENTF_SCANCODE | Win32.KEYEVENTF_KEYUP; if (VirtualKeys.IsExtended(vk)) flags |= Win32.KEYEVENTF_EXTENDEDKEY; SendKey(new Win32.KEYBDINPUT { wVk = vk, wScan = scan, dwFlags = flags }); } /// /// 组合键,如 "Ctrl+A"、"Ctrl+Shift+Esc":修饰键依次按下,主键按下弹起,修饰键逆序弹起。 /// public void HotKey(string expression) { var parts = expression.Split('+', StringSplitOptions.TrimEntries | StringSplitOptions.RemoveEmptyEntries); if (parts.Length == 0) throw new ArgumentException($"无法解析组合键:{expression}"); var vks = parts.Select(ResolveOrThrow).ToArray(); for (int i = 0; i < vks.Length - 1; i++) KeyDownVk(vks[i]); Thread.Sleep(40); KeyDownVk(vks[^1]); Thread.Sleep(40); KeyUpVk(vks[^1]); for (int i = vks.Length - 2; i >= 0; i--) { Thread.Sleep(20); KeyUpVk(vks[i]); } } /// /// 输入整段文本(含中文),使用 KEYEVENTF_UNICODE,不依赖键盘布局。 /// public void TypeText(string text) { foreach (char c in text) { SendKey(new Win32.KEYBDINPUT { wScan = c, dwFlags = Win32.KEYEVENTF_UNICODE }); SendKey(new Win32.KEYBDINPUT { wScan = c, dwFlags = Win32.KEYEVENTF_UNICODE | Win32.KEYEVENTF_KEYUP }); } } private static ushort ResolveOrThrow(string name) => VirtualKeys.Resolve(name) ?? throw new ArgumentException($"未知按键名:\"{name}\"(可用如 A、F5、ENTER、SPACE、方向键等)"); } }