SendInput 是 AHK v1 里常用的高速发送方式。很多人写脚本时会直接加一句 SendMode Input,然后默认所有发送都会更快。但实际使用中你可能会遇到一个奇怪现象:同样的脚本,有时很快,有时突然变慢,甚至还会漏按键。

这个问题经常和键盘钩子有关。AHK 为了实现热字符串、条件热键、自定义组合键、通配热键等功能,会安装低级键盘钩子。钩子一旦参与输入流程,SendInput 的行为就可能发生变化。

一、SendInput 快在哪里

SendInput 的优势是批量、快速、通常不容易和用户真实输入交织。录入文本、发送宏命令、执行一串快捷键时,它一般比默认的 SendEvent 更快。

#Requires AutoHotkey v1.1

SendMode, Input
SetKeyDelay, -1, -1

F1::
Send, 这是一段快速发送的文本
return

但要注意,SetKeyDelay 主要影响 SendEvent,对 SendInput 的影响很有限。很多人以为 SetKeyDelay, -1, -1 是让 SendInput 更快,其实真正切换发送方式的是 SendMode, Input

二、哪些功能会用到键盘钩子

AHK v1 中这些写法都可能让脚本安装键盘钩子:

  • 热字符串,例如 ::btw::by the way
  • #If 条件热键。
  • *$~ 修饰的热键。
  • Up 热键。
  • 自定义组合键,例如 a & b::
  • Input 命令或需要监听物理按键状态的脚本。

这些功能本身没有问题,问题在于它们会改变输入流的处理方式。脚本越多、热键越复杂,越容易出现“为什么 SendInput 没以前快”的疑问。

三、为什么有钩子时 SendInput 会变慢

当另一个 AHK 脚本安装了键盘钩子时,AHK 可能会把 SendInput 退化成类似 SendEvent 的方式,避免发送出来的按键被其他 AHK 钩子吞掉或乱序。这样一来,SendInput 的速度优势就没了。

如果只有当前脚本自己的钩子,AHK 可能会在调用 SendInput 时临时卸载自身钩子,发送完再装回去。这通常能恢复速度,但也会带来另一个边缘问题:在钩子短暂卸载期间,原本应该被热键拦截的物理按键可能漏到目标程序里。

四、有钩子时,SendEvent 反而更可控

如果脚本依赖热字符串、条件热键或物理按键状态,稳定性往往比极限速度更重要。此时可以显式使用 SendEvent,并把延迟调低。

SetKeyDelay, -1, 0

$z::
while GetKeyState("z", "P")
{
    SendEvent, {n down}
    Sleep, 200
    SendEvent, {n up}
}
return

这里的 $z 会强制使用键盘钩子,避免 Send 自己触发自己。既然这个场景本来就依赖钩子,显式使用 SendEvent 反而更容易控制。

五、SendInput 不一定能触发另一个热键

有些人会写一个脚本发送按键,希望触发另一个脚本里的热键。这个思路不一定可靠。简单热键可能通过 Windows 的 RegisterHotkey 机制触发,但带 *~$#IfUp 或热字符串的规则通常依赖钩子,不应该假设 SendInput 一定能触发它们。

如果确实需要脚本之间互相触发,优先考虑这几种方式:

  • 把热键里的逻辑抽成函数,直接调用函数。
  • PostMessage / SendMessage 通知另一个脚本。
  • WM_COPYDATA 传递短命令或字符串。
  • 必要时再测试 SendLevel / #InputLevel

六、排查 SendInput 变慢的顺序

  1. 先关掉其他常驻 AHK 脚本,只留当前脚本测试。
  2. 检查当前脚本有没有热字符串、#If*$~Up 热键。
  3. Send 分别改成 SendInputSendEventSendPlay 测试。
  4. 如果是游戏、远程桌面、虚拟机或管理员权限窗口,单独测试权限和兼容性。
  5. 不要只看速度,也要看是否漏键、乱序、夹入用户输入。

我的建议是:普通文本录入优先试 SendInput;依赖热键状态、物理按键、游戏宏时,不要迷信 SendInput,稳定比极限速度更重要。

相关专题

参考来源

声明:站内资源为整理优化好的代码上传分享与学习研究,如果是开源代码基本都会标明出处,方便大家扩展学习路径。请不要恶意搬运,破坏站长辛苦整理维护的劳动成果。本站为爱好者分享站点,所有内容不作为商业行为。如若本站上传内容侵犯了原著者的合法权益,请联系我们进行删除下架。