Send / SendText / SendInput / SendPlay / SendEvent

发送模拟键击和鼠标点击到活动窗口.

Send Keys
SendText Keys
SendInput Keys
SendPlay Keys
SendEvent Keys

参数

Keys

类型: 字符串

要发送的按键序列.

默认情况下(也就是说, 如果既不使用 SendText, 也不使用原始模式或文本模式), 字符 ^+!#{} 具有特殊含义. 字符 ^+!# 分别代表修饰符键 Ctrl, Shift, Alt 和 Win. 他们仅影响紧跟着的下一个键. 若要发送修饰符本身对应的键, 将按键名称括在大括号中. 若要按下(按住) 或松开按键, 下面所示的单词 "down" 或 "up" 跟在按键名称的后面.

符号 按键 按下 松开 示例
^ {Ctrl} {Ctrl down} {Ctrl up} Send "^{Home}" 按下 Ctrl+Home
+ {Shift} {Shift down} {Shift up} Send "+abC" 发送文本 "AbC"
Send "!+a" 按下 Alt+Shift+A
! {Alt} {Alt down} {Alt up} Send "!a" 按下 Alt+A
# {LWin}
{RWin}
{LWin down}
{RWin down}
{LWin up}
{RWin up}
Send "#e" 按住 Win 键时, 按下字母 E

注意: 由于大写字母是通过发送 Shift 产生的, 因此在某些程序中 A 和 a 会产生不同的效果. 例如, !A 按下 Alt+Shift+A, 而 !a 按下 Alt+A. 如果不确定, 请使用小写字母.

字符 {} 用于括起键名和其他选项, 并发送特殊的原义字符. 例如, {Tab} 是 Tab, 而 {!} 是原义的感叹号.

将一个纯 ASCII 字母(a-z 或 A-Z) 括在大括号中强制它作为相应的虚拟键码发送, 即使该字符在当前键盘布局上不存在. 换句话说, Send a 产生字母 "a", 而 Send {a} 根据键盘布局, 可能产生也可能不产生 "a". 有关详情, 请参阅下面的注释.

Send 的变体

Send: 默认情况下, Send 等同于 SendInput; 但是可以通过 SendMode 使其等同于 SendEvent 或 SendPlay.

SendText: 类似于 Send, 除了 Keys 中的所有字符都按原义解释. 有关详情, 请参阅文本模式.

SendInput 和 SendPlay: SendInput 和 SendPlay 使用与 SendEvent 相同的语法, 但通常更快更可靠. 此外, 它们在发送过程中缓冲任何物理键盘或鼠标活动, 这可以防止用户的击键与发送的击键穿插在一起. 通过 SendMode 可以使 Send 等同于 SendInput 或 SendPlay. 有关每种模式的更多信息, 请参阅下面的 SendInput 和 SendPlay.

SendEvent: SendEvent 使用 Windows keybd_event 函数发送键击(有关详情, 请在 Microsoft Docs 搜索). 发送击键的速率由 SetKeyDelay 决定. 通过 SendMode 可以使 Send 等同于 SendEvent 或 SendPlay.

特殊模式

以下模式影响 Keys 中字符的解释, 或键发送函数(例如 Send, SendInput, SendPlay, SendEvent 和 ControlSend) 的行为. 这些模式必须在 Keys 中指定 {x}, 其中 x 可以是 Raw, Text 或 Blind. 例如, {Raw}.

原始模式

可以使用 {Raw} 启用原始模式, 这会导致所有后续字符, 包括特殊字符 ^+!#{}, 都按原义进行解释, 如 {Enter} 不会转换为 Enter, ^c 不会转换为 Ctrl+C, 等等. 例如, Send "{Raw}{Tab}" 发送 {Tab}, 而不是 Tab.

原始模式不影响转义序列和表达式的解释. 例如, Send "{Raw}``100`%" 发送字符 `100%.

文本模式

可以使用 {Text}, SendText 或 ControlSendText 来启用文本模式, 与原始模式类似, 不同之处在于不会尝试将字符(`r, `n, `t 和 `b 除外) 转换为键码; 作为代替, 后备方法适用于所有剩余的字符. 对于 SendEvent, SendInput 和 ControlSend, 这提高了可靠性, 因为字符对正确的修饰符状态的依赖性要小得多. 文本模式可以与盲从模式结合使用, 以避免释放任何修饰键: Send "{Blind}{Text}your text". 但是, 一些应用程序会要求修饰键被释放.

`n, `r 和 `r`n 都被转换为一次单独的 Enter, 不像普通模式和原始模式, 转换 `r`n 为两次 Enter. `t 转换为 Tab, 而 `b 转换为 Backspace, 但所有其他字符都是不经转换直接发送的.

与盲从模式类似, 文本模式忽略 SetStoreCapsLockMode(也就是说, 不会改变 CapsLock 的状态), 并且不等待 Win 被释放. 这是因为文本模式通常不依赖于 CapsLock 的状态, 并且不能触发系统 Win+L 热键. 但是, 这仅适用于当 Keys 以 {Text} 或 {Blind}{Text} 开头时.

盲从模式

可以使用 {Blind} 启用盲从模式, 该模式通过禁用通常自动执行的许多操作来使脚本按预期运行, 从而赋予脚本更多控制权. 要启用盲从模式, {Blind} 必须是字符串中的第一个项目. 它具有以下效果:

单词 "Blind" 后面可以用一个或多个修饰符号(!#^+) 以便在需要时自动释放这些修饰符. 例如, *^a::Send "{Blind^}b" 在按下 Ctrl+Shift+A 时, 将发送 Shift+B 而不是 Ctrl+Shift+B. {Blind!#^+} 可以在需要的时候释放所有的修饰符, 但是会启用盲从模式的其他效果.

在重映射按键时, 盲从模式可以在其内部使用. 例如, 重映射 a::b 会发生这样的情况: 1) 输入 "a" 时会映射为 "b"; 2) 输入大写字母 "A" 时映射为大写字母 "B"; 并且 3) 按下 Ctrl+A 时映射为按下 Ctrl+B. 如果任何修饰符指定为源按键(包括 Shift 如果源按键是大写字母), 则如上所述, 这些修饰符被排除在外. 例如 ^a::b 产生的是正常的 B, 而不是 Ctrl+B.

SendText 或 ControlSendText 不支持 {Blind}; 请使用 {Blind}{Text} 代替.

SendPlay 不完全支持盲从模式, 尤其是在处理修饰键时(Ctrl, Alt, Shift 和 Win).

Key 名称

下表中列出了可以发送的特殊按键(每个按键名称必须用大括号括起来):

按键名称 描述
{F1} - {F24} 功能键. 例如: {F12} 表示 F12.
{!} !
{#} #
{+} +
{^} ^
{{} {
{}} }
{Enter} 主键盘上的 Enter
{Escape} 或 {Esc} Esc
{Space} Space(这只适用于出现在要发送的字符串的开头或结尾的空格 -- 而在中间的空格是原义的)
{Tab} Tab
{Backspace} 或 {BS} Backspace
{Delete} 或 {Del} Del
{Insert} 或 {Ins} Ins
{Up} ↑(主键盘上的向上键)
{Down} ↓(主键盘上的向下键)
{Left} ←(主键盘上的向左键)
{Right} →(主键盘上的向右键)
{Home} Home(主键盘)
{End} End(主键盘)
{PgUp} PgUp(主键盘)
{PgDn} PgDn(主键盘)
{CapsLock} CapsLock(使用 SetCapsLockState 更可靠). 发送 {CapsLock} 之前可能要求 SetStoreCapsLockMode False.
{ScrollLock} ScrollLock(另请参阅: SetScrollLockState)
{NumLock} NumLock(另请参阅: SetNumLockState)
{Control} 或 {Ctrl} Ctrl(技术信息: 发送中性键的虚拟键码而不是左边键的扫描码)
{LControl} 或 {LCtrl} 左 Ctrl(技术信息: 发送左边键的虚拟键码而不是中性键)
{RControl} 或 {RCtrl} 右 Ctrl
{Control down} 或 {Ctrl down} 按住 Ctrl 键直到发送 {Ctrl up}. 要按住左边或右边的键, 请使用 LCtrl 或 RCtrl 替换 Ctrl.
{Alt} Alt(技术信息: 发送中性键的虚拟键码而不是左边键的扫描码)
{LAlt} 左 Alt(技术信息: 发送左边键的虚拟键码而不是中性键)
{RAlt} 右 Alt(或 AltGr, 取决于键盘布局)
{Alt down} 按住 Alt 直到发送 {Alt up}. 要按住左边或右边的键, 请使用 LAlt 或 RAlt 替换 Alt.
{Shift} Shift(技术信息: 发送中性键的虚拟键码而不是左边键的扫描码)
{LShift} 左 Shift(技术信息: 发送左边键的虚拟键码而不是中性键)
{RShift} 右 Shift
{Shift down} 按住 Shift 直到发送 {Shift up}. 要按住左边或右边的键, 请使用 LShift 或 RShift 替换 Shift.
{LWin} 左 Win
{RWin} 右 Win
{LWin down} 按住左 Win 直到发送 {LWin up}
{RWin down} 按住右 Win 直到发送 {RWin up}
{AppsKey} Menu (调用右键点击或上下文菜单)
{Sleep} Sleep
{ASC nnnnn}

发送 Alt+nnnnn 小键盘上的按键组合, 可以用来生成键盘上不存在的特殊字符. 要生成 ASCII 字符, 请指定一个介于 1 和 255 之间的数字. 要生成 ANSI 字符(在大多数语言中的标准), 请指定一个介于 128 和 255 之间的数字, 但需要在数字前加上一个前导零, 例如 {Asc 0133}..

要生成 Unicode 字符, 请指定一个介于 256 和 65535 之间的数字(不带前导零). 但是, 有些应用程序不支持这种方法. 对于替代方法, 请参阅下面的部分.

{U+nnnn}

发送 Unicode 字符, 其中 nnnn 为字符的不包括 0x 前缀的十六进制值. 通常不需要这么做, 因为 Send 和 ControlSend 自动支持 Unicode 文本.

会使用 SendInput() 或 WM_CHAR 来发送字符, 并且当前的发送模式没有效果. 以这种方式发送的字符通常不会触发快捷键或热键.

{vkXX}
{scYYY}
{vkXXscYYY}

发送虚拟键为 XX 和扫描码为 YYY 的按键. 例如: Send "{vkFFsc159}". 如果省略 sc 或 vk 部分, 则发送最合适的值.

XX 和 YYY 的值是十六进制的, 通常可以从主窗口的 View->Key history 菜单项中确定. 另请参阅: 特殊按键

警告: 以这种方式组合 vk 和 sc 仅在 Send 有效.

{Numpad0} - {Numpad9} 小键盘上的数字键(与 NumLock 打开时输入的一样). 例如: {Numpad5} 为数字 5.
{NumpadDot} .(小键盘上的点)(与 NumLock 打开时输入的一样).
{NumpadEnter} 小键盘上的 Enter
{NumpadMult} *(小键盘上的乘号)
{NumpadDiv} /(小键盘上的除号)
{NumpadAdd} +(小键盘上的加号)
{NumpadSub} -(小键盘上的减号)
{NumpadDel} 小键盘上的 Del(当 NumLock 为 OFF 时, 此键和以下的小键盘按键将被使用)
{NumpadIns} 小键盘上的 Ins
{NumpadClear} 小键盘上的 Clear 键(在 NumLock 关闭时, 通常为 5).
{NumpadUp} 小键盘上的 ↑(向上)
{NumpadDown} 小键盘上的 ↓(向下)
{NumpadLeft} 小键盘上的 ←(向左)
{NumpadRight} 小键盘上的 →(向右)
{NumpadHome} 小键盘上的 Home
{NumpadEnd} 小键盘上的 End
{NumpadPgUp} 小键盘上的 PgUp
{NumpadPgDn} 小键盘上的 PgDn
{Browser_Back} 浏览器 "后退" 按钮
{Browser_Forward} 浏览器 "前进" 按钮
{Browser_Refresh} 浏览器 "刷新" 按钮
{Browser_Stop} 浏览器 "停止" 按钮
{Browser_Search} 浏览器 "搜索" 按钮
{Browser_Favorites} 浏览器 "收藏" 按钮
{Browser_Home} 启动浏览器并打开主页
{Volume_Mute} 主音量静音/取消静音. 通常相当于 SoundSetMute -1.
{Volume_Down} 减小主音量. 通常相当于 SoundSetVolume -5.
{Volume_Up} 增加主音量. 通常相当于 SoundSetVolume "+5".
{Media_Next} 在媒体播放器中播放下一曲目
{Media_Prev} 在媒体播放器中播放前一曲目
{Media_Stop} 停止媒体播放器
{Media_Play_Pause} 播放/暂停媒体播放器
{Launch_Mail} 启动电子邮件程序
{Launch_Media} 启动媒体播放器
{Launch_App1} 启动用户程序 1
{Launch_App2} 启动用户程序 2
{PrintScreen} PrtScr
{CtrlBreak} Ctrl+Pause
{Pause} Pause
{Click [Options]} Send 鼠标点击使用的选项与 Click 函数中的一样. 例如, Send "{Click}" 会在鼠标光标当前位置点击一次鼠标左键, 而 Send "{Click 100 200}" 则在坐标 100, 200 处点击(这里的坐标模式取决于 CoordMode). 要移动鼠标而不点击, 请在坐标后指定 0; 例如: Send "{Click 100 200 0}". 鼠标点击之间的延迟由 SetMouseDelay 决定(而不是 SetKeyDelay).
{WheelDown}, {WheelUp}, {WheelLeft}, {WheelRight}, {LButton}, {RButton}, {MButton}, {XButton1}, {XButton2}

在光标的当前位置发送一个鼠标按钮事件(要控制位置和其他选项, 请使用上面的 {Click}). 鼠标点击之间的延迟由 SetMouseDelay 决定.

LButton 和 RButton 分别对应鼠标的主按钮和次按钮. 通常鼠标的主按钮(LButton) 在左边, 但是用户可以通过系统设置来交换按钮.

{Blind} 启用盲从模式, 通过禁用一些通常会自动完成的事情, 让脚本有了更多的控制权, 从而使事情一般都能正常工作. {Blind} 必须出现在字符串的开头.
{Raw} 启用原始模式, 这将导致以下字符按原义解释: ^+!#{}. 虽然 {Raw} 不需要出现在字符串的开头, 但一旦指定, 它将在字符串的其余部分保持有效.
{Text} 启用文本模式, 它发送的是字符流而不是按键. 与原始模式一样, 文本模式会使以下字符按原义解释: ^+!#{}. 虽然 {Text} 不需要出现在字符串的开头, 但一旦指定, 它将在字符串的其余部分保持有效.

重复或按住按键

重复键击: 用大括号括起按键名称和重复次数. 例如:

Send "{DEL 4}"  ; 按 4 次 Delete 键.
Send "{S 30}"   ; 发送 30 次大写字母 S.
Send "+{TAB 4}"  ; 按 4 次 Shift-Tab.

按住或释放按键: 用大括号括起按键名称和单词 Down 或 Up. 例如:

Send "{b down}{b up}"
Send "{TAB down}{TAB up}"
Send "{Up down}"  ; 按下向上键.
Sleep 1000  ; 按住 1 秒.
Send "{Up up}"  ; 释放向上键.

使用上面的方法按住一个按键后, 这个期间它不会像您实际按住这个按键一样自动重复(这是由于自动重复是一个驱动/硬件的特性). 不过, 可以使用 Loop 来模拟自动重复. 下面的例子中发送 20 次 tab 键击:

Loop 20
{
    Send "{Tab down}"  ; 自动重复由连续的按下事件组成(没有弹起事件).
    Sleep 30  ; 在两次键击之间的毫秒数(或使用 SetKeyDelay 设置).
}
Send "{Tab up}"  ; 松开按键.

默认情况下, 如果一个修饰键在发送时被 "按下", 则 Send 不会自动释放该修饰键(Control, Shift, Alt 和 Win) . 例如, 如果用户物理按下 Ctrl 时, Send "a" 的行为类似于 Send "{Blind}{Ctrl up}a{Ctrl down}", 但 Send "{Ctrl Down}" 后面接着 Send "a" 将产生 Ctrl+A. DownTemp 和 DownR 可以用来覆盖这种行为. DownTemp 和 DownR 与 Down 具有同样的效果, 除了修饰键(Control, Shift, Alt 和 Win).

DownTemp 告诉后续的发送, 该键不是永久按下的, 只要有按键需要就可以释放. 例如, 在发送 Send "{Control DownTemp}" 之后, 再 Send "a" 将产生一个正常的 A, 而不是 Ctrl+A. 任何使用 Send 的方法都有可能永久地释放修饰键, 所以 DownTemp 并不是重映射修饰键的理想选择.

DownR(其中 "R" 表示重映射, 这是它的主要用途) 告诉后续的发送, 如果该键被自动释放, 则应在发送结束后再次按下. 例如, Send "{Control DownR}" 后面跟着 Send "a" 会产生一个正常的 A, 而不是 Ctrl+A, 但会让 Ctrl 处于被按下的状态, 以便用于键盘快捷键. 换句话说, DownR 有类似于物理按下按键的效果.

如果某个字符与当前键盘布局上的虚拟键不一致, 则不能 "按下" 或 "释放". 例如, Send "{μ up}" 对大多数键盘布局没有效果, 而 Send "{μ down}" 等同于 Send "μ".

备注

字符 vs. 按键: 默认情况下, 先将字符转换为按键来发送字符. 如果这种转换是不可能的(即, 如果当前的键盘布局不包含产生该字符的键或键组合), 则通过以下回退方法之一来发送字符:

注意: 使用上述方法发送字符通常不会触发键盘快捷键或热键.

对于 a-z 或 A-Z(纯 ASCII 字母) 范围内的字符, 每个当前键盘布局中不存在的字符可以作为字符或相应的虚拟键码(vk41-vk5A) 发送:

如果字母存在于当前的键盘布局中, 那么它总是以布局与该字母相关联的键码发送(除非使用了文本模式, 在这种情况下, 该字符将通过其他方式发送). 换句话说, 上面的部分只适用于非拉丁语系的布局, 如俄语.

修饰键状态: 当 Send 需要改变 Win 或 Alt 修饰键的状态时(比如用户按住其中一个键), 它可能会注入额外的按键(默认为 Ctrl) 来阻止开始菜单或窗口菜单的出现. 有关详情, 请参阅 A_MenuMaskKey.

BlockInput 对比 SendInput/SendPlay: 尽管 BlockInput 函数可以用来防止用户物理输入的任何按键破坏模拟按键的流, 但通常最好使用 SendInput 或 SendPlay 这样按键和鼠标点击就不会中断. 这是因为与 BlockInput 不同的是, SendInput/Play 不会在发送过程中丢弃用户输入的内容; 相反, 这样的按键会被缓冲并在之后发送.

当发送大量的按键时, 可以使用延续片段来提高可读性和可维护性.

由于操作系统不允许模拟 Ctrl+Alt+Del 组合, 所以类似 Send "^!{Delete}" 这样的操作是没有效果的.

当活动窗口以管理身份运行而当前脚本不是时, Send 可能没有效果. 这是由于一种叫做用户界面特权隔离的安全机制造成的.

SendInput

一般情况下, SendInput 是发送按键和鼠标点击的首选方法, 因为它的速度和可靠性都很高. 在大多数情况下, SendInput 几乎是瞬间完成的, 即使是发送长字符串时也是如此. 由于 SendInput 的速度如此之快, 它的可靠性也更高, 因为这样其他一些窗口更没有机会出乎意料地弹出并打断按键. 用户在 SendInput 过程中输入的任何东西都会被推迟到之后再进行, 从而进一步提高了可靠性.

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

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

如果执行 SendInput 的脚本 以外的 脚本安装了低级键盘钩子, 则 SendInput 会自动恢复为 SendEvent(或当 SendMode "InputThenPlay" 生效时为 SendPlay). 这是由于外部钩子的存在让 SendInput 失去了所有的优势, 使它不如 SendPlay 和 SendEvent 两者. 然而, 由于 SendInput 无法检测到除 AutoHotkey v1.0.43+ 以外的程序中的低级钩子, 所以在这些情况下它不会还原, 使得它的可靠性不如 SendPlay/Event.

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

SendPlay

警告: 如果启用了 UAC, 即使脚本以管理员身份运行, SendPlay 也可能没有效果. 有关详情, 请参阅 FAQ.

SendPlay 最大的优势在于它能在更多的游戏中 "回放" 按键和鼠标点击. 例如, 某款游戏只有在有 SendPlay 选项的情况下才能接受热字串.

在这三种发送模式中, SendPlay 是最特别的, 因为它本身并不模拟按键和鼠标点击. 相反, 它创建了一系列的事件(消息), 直接流向活动窗口(类似于 ControlSend, 但级别较低). 因此, 不会触发热键或热字串.

和 SendInput 一样, SendPlay 的按键与用户键入的按键互不干扰. 因此, 如果用户在 SendPlay 期间碰巧输入了一些东西, 这些键程会被推迟到之后.

虽然 SendPlay 比 SendInput 要慢很多, 但它通常比传统的 SendEvent 模式要快(即使 KeyDelay 为 -1 时, 也是如此).

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

SendPlay 不使用 SetKeyDelay 和 SetMouseDelay 的标准设置. 相反, 它默认为无延迟, 可以按照下面的例子来改变:

SetKeyDelay 0, 10, "Play"  ; 注意 0 和 -1 在 SendPlay 模式中是一样的.
SetMouseDelay 10, "Play"

SendPlay 无法打开或关闭 CapsLock, NumLock 或 ScrollLock. 同样, 它也无法改变 GetKeyState 所看到的键的状态, 除非按键被发送到脚本自己的一个窗口. 即使如此, 任何对左/右修饰键(例如 RControl) 的改变也只能通过它们的中性对应键(例如 Control) 来检测. 此外, SendPlay 还有其他限制, 在 SendMode 页面上有描述.

与 SendInput 和 SendEvent 不同, 用户可以通过按下 Ctrl+Alt+Del 或 Ctrl+Esc 来中断 SendPlay. 当这种情况发生时, 剩余的按键不会被发送, 但是脚本会继续执行, 就像 SendPlay 已经正常完成一样.

虽然 SendPlay 可以发送 LWin 和 RWin 事件, 但是它们会直接发送到活动窗口, 而不是执行它们的在操作系统中的原生功能. 要解决这个问题, 请使用 SendEvent. 例如, SendEvent "#r" 将显示开始菜单的运行对话框.

SendMode, SetKeyDelay, SetStoreCapsLockMode, 转义序列(例 `n), ControlSend, BlockInput, 热字串, WinActivate

示例

输入两行签名.

Send "Sincerely,{enter}John Smith"

选择 File->Save 菜单(Alt+F 后面跟着 S).

Send "!fs"

到文本的末尾然后发送四次 shift 和左方向键组合的键击.

Send "{End}+{Left 4}"

通过最快的方法发送一长串原始字符.

SendInput "{Raw}A long series of raw characters sent via the fastest method."
0x8