SendMode [v1.0.43+]

Send 和 SendInput 或 SendPlay 具有相同的功能而不是默认的(SendEvent). 也使 Click, MouseClick, MouseClickDragMouseMove 使用指定的模式.

SendMode, Mode

参数

Mode

指定以下单词之一, 即可更改后续出现的 Send, SendRaw, Click, MouseClick, MouseClickDragMouseMove 的发送模式:

Event: 默认模式. 切换到传统的 SendEvent 模式.

Input: 切换到 SendInput 模式, 这是发送模拟按键操作和鼠标点击的最快且通常也是最可靠的方法.

Play: 切换到 SendPlay 模式, 此模式比 SendEvent 模式更快, 并且在其他模式无法正常工作的情况下, 例如某些游戏或具有特殊输入处理方式的应用程序中, 仍能发挥作用.

InputThenPlay [v1.0.43.02+]: 与 Input 相同, 但当Input 不可用时, 它不会回退到 Event, 而是恢复到 Play. 这也会导致 SendInput 命令本身在 Input 不可用时, 恢复到 Play.

发送模式

以下部分将介绍 AutoHotkey 使用的三种发送模拟按键操作和鼠标点击的操作方式: SendEvent, SendInputSendPlay. 每种模式都有其各自的优点和局限性, 且应用程序的响应方式也会因输入的生成方式而有所不同. 了解这些差异有助于为特定脚本或目标应用程序选择最有效的模式

SendEvent

SendEvent 发送键击和鼠标点击的传统方法. 然而, 与其他发送模式相比, SendEvent 的速度较慢; 它永远无法达到 SendInputSendPlay 的速度.

SendEvent 会遵循由 SetKeyDelaySetMouseDelay 设置的延迟时间. 默认延迟时间为 10 毫秒.

当 SendInput 不可用时, 也会自动使用 SendEvent, 除非 InputThenPlay 生效.

SendEvent 命令可用于通过 SendEvent 模式显式地发送键击.

SendInput

由于 SendInput 突出的速度和可靠性, 通常为发送键击和鼠标点击的首选方法. 在大多数情况下, SendInput 是近乎瞬时发送的, 即使在发送长字符串也是如此. 由于 SendInput 如此快速, 所以也更可靠, 因为这样其他一些窗口更没有机会出乎意料地弹出并打断正发送的键击. 可靠性进一步提升是通过把用户在 SendInput 发送期间输入的内容推迟的情况而言.

与其他发送模式不同, 操作系统限制 SendInput 每次只能发送大约 5000 个字符(此限制可能因操作系统版本和性能设置而有所不同). 超过此限制的字符和事件不会被发送.

注意: SendInput 会忽略 SetKeyDelaySetMouseDelay , 因为在这种发送模式中操作系统不支持延迟. 但是, 在后面描述的情况中当 SendInput 恢复到 SendEvent 时, 它会使用 SetKeyDelay -1, 0(但如果 SendEvent 的按键延迟为 -1,-1 时, 则使用 -1,-1). 当 SendInput 恢复为 SendPlay 时, 由于 InputThenPlay 的原因, 它使用 SendPlay 的按键延迟.

如果脚本安装了底层键盘钩子, SendInput 会在执行之前自动卸载它, 然后重新安装它. 因此, SendInput 通常不能触发脚本自己的钩子热键或 InputHook. 钩子被暂时卸载, 因为它的存在会禁用 SendInput 的所有优点, 使其不如 SendPlaySendEvent. 然而, 这只能对脚本自己的钩子执行, 如果检测到外部钩子, 则不会执行, 如下所述.

如果执行 SendInput 脚本外的 其他 脚本安装了低级键盘钩子, 则 SendInput 会自动恢复为 SendEvent(或 SendPlay, 当 InputThenPlay 生效时). 这是由于外部钩子的存在让 SendInput 失去了所有的优势, 使它不如 SendPlaySendEvent. 然而, 在 [AutoHotkey v1.0.43+] 之前的版本中 SendInput 无法检测到底层键盘钩子, 在这种情况下, 将不会自动恢复, 比其他模式更不可靠.

当 SendInput 使用像 {Click} 这样的方法发送鼠标点击, 并且 CoordMode Mouse, Relative 有效时(默认), 则每次点击都会相对于发送开始时的那个活动窗口. 因此, 如果 SendInput 有意地激活另一个窗口(通过类似 alt-tab 的方法), 那么这个命令中后续点击的坐标将变成错误的, 因为它们仍然相对于原来的活动窗口而不是新的.

The SendInput 命令可用于通过 SendInput 模式显式地发送键击.

已知限制:

SendPlay

警告: SendPlay 在 UAC 启用时可能会完全失效, 即使是使用管理员权限运行脚本. 有关详情, 请参阅 FAQ.

比起其他模式 SendPlay 最大的优势是具有在相当多种游戏中 "play back" 键击和鼠标点击能力. 例如, 某种特殊的游戏可能仅接受 SendPlay 选项热字串.

在三种发送模式中, SendPlay 是最不常用的, 因为它本身并不模拟键击和鼠标点击. 作为替代, 它制造一系列事件(消息) 直接流向活动窗口(类似于 ControlSend, 但在更低的层面). 因此 SendPlay 不会触发热键或热字串.

SendInput 一样, SendPlay 的键击不会夹杂用户输入的内容. 因此, 如果用户碰巧在 SendPlay 发送期间输入了一些内容, 则它们会被延迟到发送完后.

尽管 SendPlay 明显比 SendInput 慢, 但它通常比传统的 SendEvent 模式更快(即使在 KeyDelay 为 -1 时).

如果安装了键盘钩子, 则在 SendPlay 发送期间会自动屏蔽 Win 键(LWin 和 RWin). 这样避免了在发送期间当用户无意按了 Win 键时显示开始菜单. 与之相比, LWin 和 RWin 之外的其他按键不需要屏蔽, 因为操作系统会自动把它们延迟到 SendPlay 执行完后(通过缓冲).

如果 SetKeyDelaySetMouseDelay 函数的 Play 参数存在, 则 SendPlay 会遵循这些函数所设定的延迟时间. 与 SendEvent 不一样, SendPlay 默认值为 -1(完全不设置延迟).

SendPlay 不能切换 CapsLock, NumLock 或 ScrollLock 按键的状态. 同样地, 如果键击发送到脚本自身的窗口时, 则它才能改变由 GetKeyState 获取的按键状态. 即使在此时, 对左/右修饰键的任何改变(例如 RControl) 只能通过它们的中性副本检测到(例如 Control).

SendInputSendEvent 不同, 用户通过按下 Ctrl+Alt+DelCtrl+Esc 可以打断 SendPlay 的发送. 这种情况发生时, 剩余的键击不会被发送, 不过脚本会像 SendPlay 正常结束一样继续执行.

尽管 SendPlay 能发送 LWin 和 RWin 事件, 但它们被直接发送到活动窗口而不执行它们原本的操作系统功能. 要变通解决此问题, 请使用 SendEvent. 例如, SendEvent #r 会显示开始菜单的运行对话框.

The SendPlay 命令可用于通过 SendPlay 模式显式地发送键击.

已知限制:

备注

如果 SendMode 没有使用, 则默认的模式为 Event.

由于 SendMode 也改变了 Click, MouseMove, MouseClickMouseClickDrag 的模式, 所以您有机会为特殊的鼠标事件使用不同的模式. 实现这种操作最便捷的方法是使用 {Click}. 例如:

SendEvent {Click 100 200}  ; SendEvent 使用更老更传统的方法进行点击.

如果在自动执行段(脚本的顶部) 使用了 SendMode, 那么它还会影响键盘和鼠标重映射. 尤其是您在重映射时使用了 SendMode Play, 请参阅 SendPlay 的重映射限制.

[v1.1.23+]: 内置变量 A_SendMode 包含当前的设置.

每个新运行的线程(例如 热键, 自定义菜单项定时子程序) 都会以此命令的默认设置开始. 通过在脚本的自动执行段(脚本的顶部) 使用此命令可以改变这个默认设置.

Send, SetKeyDelay, SetMouseDelay, Click, MouseClick, MouseClickDrag, MouseMove

示例

让 Send 与 SendInput 同义. 由于其卓越的速度和可靠性, 推荐新脚本使用.

SendMode Input

让 Send 与 SendInput 同义, 但如果 SendInput 不可用, 则回退到 SendPlay.

SendMode InputThenPlay