Windows平台用SendInput模拟Ctrl+V最可靠,需严格按“Ctrl↓→V↓→V↑→Ctrl↑”时序发送4个INPUT事件,每步设对应wVk和dwFlags,优先用VK_LCONTROL提升兼容性,且须确保目标窗口有焦点及权限一致。

Windows平台用SendInput模拟Ctrl+V最可靠
直接调用SendInput是Windows下模拟组合键的首选方式,它走的是系统输入队列,兼容性好、不依赖前台窗口,且不会被多数安全软件拦截。比keybd_event(已废弃)和SendMessage(仅对目标窗口有效)更稳妥。
关键点在于:必须按顺序发送“按下修饰键→按下目标键→释放目标键→释放修饰键”,且每步都要用INPUT结构体明确标记KEYDOWN或KEYUP。漏掉任一释放动作,会导致Ctrl键卡住。
示例逻辑:
// 模拟 Ctrl+V
INPUT inputs[4] = {};
// Ctrl down
inputs[0].type = INPUT_KEYBOARD;
inputs[0].ki.wVk = VK_CONTROL;
// V down
inputs[1].type = INPUT_KEYBOARD;
inputs[1].ki.wVk = 'V';
// V up
inputs[2].type = INPUT_KEYBOARD;
inputs[2].ki.wVk = 'V';
inputs[2].ki.dwFlags = KEYEVENTF_KEYUP;
// Ctrl up
inputs[3].type = INPUT_KEYBOARD;
inputs[3].ki.wVk = VK_CONTROL;
inputs[3].ki.dwFlags = KEYEVENTF_KEYUP;
SendInput(4, inputs, sizeof(INPUT));
注意VK_CONTROL和VK_LCONTROL的区别
用VK_CONTROL会触发任意一侧Ctrl键(左或右),但某些老旧程序或游戏只响应VK_LCONTROL。如果Ctrl+V没反应,优先换用VK_LCONTROL重试。
立即学习“C++免费学习笔记(深入)”;
同理,Shift、Alt也有左右之分:VK_LSHIFT/VK_RSHIFT、VK_LMENU/VK_RMENU。组合键稳定性要求高时,显式指定左侧键更保险。
常见误区:
- 混用
VK_CONTROL和VK_LCONTROL——按下用左,释放用通用,导致状态不匹配 - 忽略大小写:传
'v'而非'V',虽然wVk字段不区分,但习惯上大写更清晰 - 未设置
ki.wScan——通常可为0,但若需处理非美键盘布局,得用MapVirtualKey补全
Linux/macOS不能用SendInput,得换方案
SendInput是Windows专属API,Linux下需借助XTestFakeKeyEvent(X11)或uinput内核模块;macOS则要用CGEventCreateKeyboardEvent + CGEventPost。跨平台项目必须条件编译。
Linux X11示例要点:
- 需链接
-lX11 -lXtst - 先用
XDisplayKeycodes查键码,V通常是36,Control_L是37 - 必须调用
XSync确保事件提交,否则可能丢键
macOS注意:CGEventSetFlags要显式添加kCGEventFlagMaskControl,不能靠连发按键模拟。
权限和焦点问题常被忽略
即使代码逻辑正确,也可能失败:
- Windows:UAC高权限进程无法向低权限前台窗口发输入(如管理员CMD向普通Notepad发Ctrl+V),需保持权限层级一致
- macOS:从macOS 10.14起,必须在“系统偏好设置→隐私→辅助功能”中授权你的程序,否则
CGEventPost静默失败 - 所有平台:目标窗口若被遮挡、最小化或失去输入焦点,组合键大概率无效——
SendInput不解决焦点问题,得额外调用SetForegroundWindow或BringWindowToTop
真正难的不是发键,而是让目标应用“看到并处理”这个键。调试时先用记事本验证基础流程,再逐步切到真实目标环境。


















