如何在C#中模拟按键操作以被后台应用识别?
在C#中实现底层模拟按键(支持后台程序识别)
SendKeys.Send 本质是通过Windows消息队列向当前焦点窗口的输入控件发送文本输入消息,并非模拟真实的硬件按键事件。所以只有当聊天框这类输入控件获得焦点时,它能触发字符输入;但游戏的背包快捷键是直接监听底层键盘硬件事件,SendKeys无法触发这类逻辑。
要实现能被后台程序或游戏底层识别的模拟按键,需使用Windows API的SendInput函数——它直接模拟硬件级别的键盘输入事件,能绕过控件焦点限制,被目标程序的底层按键监听逻辑捕获。
具体实现代码
首先添加必要的命名空间引用:using System.Runtime.InteropServices;,然后封装键盘模拟类:
using System; using System.Runtime.InteropServices; public class KeyboardSimulator { // 输入类型枚举 private enum InputType : uint { InputKeyboard = 1 } // 键盘输入结构体 [StructLayout(LayoutKind.Sequential)] private struct KEYBDINPUT { public ushort wVk; public ushort wScan; public uint dwFlags; public uint time; public IntPtr dwExtraInfo; } // 通用输入结构体 [StructLayout(LayoutKind.Sequential)] private struct INPUT { public InputType type; public KEYBDINPUT ki; } // 导入SendInput API [DllImport("user32.dll", SetLastError = true)] private static extern uint SendInput(uint nInputs, INPUT[] pInputs, int cbSize); // 导入VkKeyScan:将字符转为虚拟键码 [DllImport("user32.dll")] private static extern short VkKeyScan(char ch); // 导入MapVirtualKey:转换虚拟键码为扫描码 [DllImport("user32.dll")] private static extern uint MapVirtualKey(uint uCode, uint uMapType); // 模拟字符按键的按下+释放 public static void SimulateKeyPress(char keyChar) { short keyCode = VkKeyScan(keyChar); ushort virtualKey = (ushort)(keyCode & 0xFF); ushort scanCode = (ushort)MapVirtualKey(virtualKey, 0); ExecuteKeyEvent(virtualKey, scanCode); } // 模拟指定虚拟键码的按键按下+释放 public static void SimulateKeyPress(ushort virtualKey) { ushort scanCode = (ushort)MapVirtualKey(virtualKey, 0); ExecuteKeyEvent(virtualKey, scanCode); } // 执行按键按下和释放的核心逻辑 private static void ExecuteKeyEvent(ushort virtualKey, ushort scanCode) { INPUT[] inputs = new INPUT[2]; // 按下按键 inputs[0].type = InputType.InputKeyboard; inputs[0].ki.wVk = virtualKey; inputs[0].ki.wScan = scanCode; inputs[0].ki.dwFlags = 0; // 释放按键 inputs[1].type = InputType.InputKeyboard; inputs[1].ki.wVk = virtualKey; inputs[1].ki.wScan = scanCode; inputs[1].ki.dwFlags = 0x0002; // KEYEVENTF_KEYUP标记 SendInput(2, inputs, Marshal.SizeOf(typeof(INPUT))); } }
使用示例
// 方式1:直接模拟字符'i'的按键 KeyboardSimulator.SimulateKeyPress('i'); // 方式2:使用虚拟键码(VK_I的虚拟键码为0x49) KeyboardSimulator.SimulateKeyPress(0x49);
补充说明
SendInput直接向系统输入队列注入硬件级事件,游戏的底层按键监听逻辑能正常识别,不会局限于前台输入控件。- 若目标游戏有反作弊机制,可能会拦截
SendInput调用,这种情况下需要驱动级别的模拟工具,但开发复杂度和权限要求更高。 - 运行程序时若无效果,可尝试以管理员身份启动,确保进程有足够权限发送系统输入事件。
内容的提问来源于stack exchange,提问作者Максим Мельник
相关产品推荐
相关产品推荐

