热键(鼠标, 控制器和键盘快捷键)

目录

介绍和简单示例

热键有时也称为快捷键, 因为它们能简便地触发动作(例如运行程序或键盘宏). 在下面的例子中, Win+N 被设置为启动记事本. 磅的符号 [#] 表示 Win, 它被称为 修饰符:

#n::
Run Notepad
return

在前面的最后一行中, return 用来结束此热键. 不过, 如果热键只需要执行单行语句, 那么此行可以直接放在双冒号的右边. 换句话说, return 可以省略:

#n::Run Notepad

要在热键中使用多个修饰键, 那么需要把它们连续地列出来(顺序无关紧要). 下面的例子中使用 ^!s 来表示 Ctrl+Alt+S:

^!s::
Send Sincerely,{enter}John Smith  ; 此行发送键击到活动(最前面的) 窗口.
return

热键修饰符

在定义热键时您可以使用下列修饰符:

符号 描述
#

Win (Windows 徽标键).

[v1.0.48.01+]: 对于 Windows Vista 及以上版本, 包含 Win 的热键(例如 #a) 会等待 Win 被释放后才发送任何包含 L 的文本. 这样避免了这种热键中的 Send 锁定 PC. 这种行为适用于除 SendPlay(这里不需要) 和盲从模式(Blind) 外的所有发送模式. [v1.1.29+]: 文本模式也被排除在外.

注意: 按下包含 Win 的热键可能会导致额外的模拟击键(默认为 Ctrl). 请参阅 #MenuMaskKey.

!

Alt

注意: 按下包含 Alt 的热键可能会导致额外的模拟击键(默认为 Ctrl). 请参阅 #MenuMaskKey.

^ Ctrl
+ Shift
& 和符号可以用来组合任意两个按键或鼠标按钮, 让它们成为自定义热键. 详情请参阅下文.
< 使用成对按键中左边的那个. 例如 <!a 相当于 !a, 只是使用左边的 Alt 才可以触发.
> 使用成对按键中右边的那个.
<^>!

AltGr(alternate graph, or alternate graphic)(译者注: 标准键盘上没有该键). 如果您键盘布局中含 AltGr 而非右 Alt, 那么这一系列符号一般可用于表示 AltGr. 例如:

<^>!m::MsgBox You pressed AltGr+m.
<^<!m::MsgBox You pressed LeftControl+LeftAlt+m.

或者, 让 AltGr 自己成为热键, 请使用下面的热键(不像上面出现的任何热键):

LControl & RAlt::MsgBox You pressed AltGr itself.
*

通配符: 即使附加的修饰键被按住也能激发热键. 这常与重映射按键或按钮组合使用. 例如:

*#c::Run Calc.exe  ; Win+C, Shift+Win+C, Ctrl+Win+C 等都会触发此热键.
*ScrollLock::Run Notepad  ; 即使在按住其他修饰键时按下 ScrollLock 也会触发此热键.

通配符热键总是使用键盘钩子, 因此通配符热键使按下任何热键失效. 例如, *a:: 出现后会将 ^a:: 改为使用键盘钩子.

~

触发热键时, 热键中按键原有的功能不会被屏蔽(对操作系统隐藏). 在下面的两个例子中, 用户的鼠标按钮点击会被发送到活动窗口:

~RButton::MsgBox You clicked the right mouse button.
~RButton & C::MsgBox You pressed C while holding down the right mouse button.

与其他前缀符号不同, 可以在热键的某些变体中使用颚化符(波浪号) 前缀而其他的不使用. 然而, 如果应用于颚化符(波浪号) 前缀的任何自定义组合键没有被关闭或暂停, 它会影响那个前缀键在 所有 组合中的行为.

用于替代 alt-tab 的特殊按键总是忽略颚化符(波浪号) 前缀.

[v1.1.14+]: 如果把颚化符(前缀键) 用在自定义修饰键中且此修饰键自身也作为热键, 则在按下此修饰键时会触发热键而不会被延迟到按键释放的时候. 例如, 上文中 ~RButton 热键在按下此按键时就会触发. 对于 [v1.1.14] 之前的版本(或未使用颚化符前缀), 则会在按键释放时触发其自身的热键, 不过仅在未触发 RButton & C 组合键的时候.

如果颚化符前缀只应用于自定义组合键, 而不应用于非组合热键, 按键的原生功能将持续被屏蔽. 例如, 下面的脚本, 按住 Menu 将会一直显示一个工具提示而不会触发上下文菜单:

AppsKey::ToolTip Press < or > to cycle through windows.
AppsKey Up::ToolTip
~AppsKey & <::Send !+{Esc}
~AppsKey & >::Send !{Esc}

只要有一个键盘热键有颚化符修饰, 热键总是使用键盘钩子.

$

通常只在脚本使用 Send 命令发送包含了热键自身的按键时才需要使用此符号, 否则可能会导致热键触发自己. $ 前缀强制使用键盘钩子来实现此热键, 作为副作用这样阻止了 Send 命令触发它自己. $ 前缀相当于在此热键定义之前的某个位置指定了 #UseHook.

$ 前缀对于鼠标热键不起作用, 因为它们始终使用鼠标钩子. 它对于已经启用了键盘钩子的热键同样无效, 包括任何带有颚化符(~)通配符(*) 修饰符的热键, key-up 热键以及自定义组合. 要确定特定热键是否使用了键盘钩子, 请使用 ListHotkeys 查看.

[v1.1.06+]: #InputLevelSendLevel 对 Send 命令是否触发热键和热字串提供了额外的控制功能.

UP

单词 UP 可以跟在热键名后面使得在释放按键时触发热键, 而不是按下时. 下面的例子把左 Win 重映射为左 Ctrl:

*LWin::Send {LControl down}
*LWin Up::Send {LControl up}

"Up" 也可以用于普通热键中, 例如: ^!r Up::MsgBox You pressed and released Ctrl+Alt+R. 它还可以用在组合键(例如 F1 & e Up::)

限制: 1) "Up" 不能和控制器按钮一起使用; 2) 在没有普通/按下热键副本的 "Up" 热键会完全接管那个按键以防被卡住. 避免这种情况的一种方法是添加颚化符(波浪号) 前缀(例如 ~LControl up::)

"Up" 热键和其同行的键(如果有的话) 总是使用键盘钩子.

相关提示, 类似于上面的一种技术是让热键成为前缀键. 好处是尽管热键会在按键松开时激发, 但仅在您之前按住此前缀键时没有按其他任何键的情况下才会如此. 例如:

LControl & F1::return  ; 通过把左 control 键放在 "&" 前面至少一次来让它成为前缀键.
LControl::MsgBox You released LControl without having used it to modify any other key.

注意: 请参阅按键列表来了解键盘按键和鼠标/控制器按钮的完整列表.

多个热键可以垂直地叠放来让它们执行相同的动作. 例如:

^Numpad0::
^Numpad1::
MsgBox Pressing either Control+Numpad0 or Control+Numpad1 will display this message.
return

通过不为按键或按键组合的热键指定任何操作可以在整个系统中完全禁用它们. 下面的例子中禁用了右 Win:

RWin::return

上下文相关的热键

#IfWinActive/Exist#If 指令可以用来让热键根据不同的条件执行不同的动作(或什么都不做). 例如:

#IfWinActive ahk_class Notepad
^a::MsgBox 你在记事本中按下了 Ctrl-A. 而在其他窗口中按下 Ctrl-A 将原样发送.
#c::MsgBox 你在记事本中按下了 Win-C 组合键.

#IfWinActive
#c::MsgBox 你在非记事本程序中按下了 Win-C .

#If MouseIsOver("ahk_class Shell_TrayWnd") ; 有关 MouseIsOver, 请参阅 #If 示例 1.
WheelUp::Send {Volume_Up}     ; 在任务栏上滚动滚轮: 增加/减小音量.
WheelDown::Send {Volume_Down} ;

自定义组合键

通常快捷键组合由可选的前缀/修饰键(Ctrl, Alt, Shift 和 LWin/RWin) 和单个后缀键组成. 标准的修饰键就是这样设计的, 所以按下时通常没有立即效果.

两个按键(包括鼠标, 但不包括控制器按钮) 的自定义组合热键可以通过在它们之间使用 "&" 来定义. 因为它们是为与前缀键一起使用而设计的, 所以自定义组合有以下特殊行为:

注意: 对于带有标准修饰键的组合, 通常最好使用标准语法. 例如, 使用 <+s:: 而不是 LShift & s::.

在下面的例子中, 你可以按住 Numpad0, 然后按下第二个按键来触发热键:

Numpad0 & Numpad1::MsgBox You pressed Numpad1 while holding down Numpad0.
Numpad0 & Numpad2::Run Notepad

前缀键导致失去它原有的功能: 在上面的例子中, Numpad0 成为 前缀键; 但是这也让 Numpad0 在被按下时失去了它原有的功能. 为了避免此问题, 脚本中可以配置 Numpad0 执行新的动作, 例如下列热键的其中一个:

Numpad0::WinMaximize A   ; 最大化活动/前端窗口.
Numpad0::Send {Numpad0}  ; 让 Numpad0 释放 时产生 Numpad0 键击. 请参阅下面的注释.

释放时触发: 使用上面的其中一个自定义组合热键可以在 释放 Numpad0 时执行指定的动作, 但不包括按住 Numpad0 时您又按下了其他按键的情况. 从 [v1.1.14+] 开始, 可以在其中某个热键前使用颚化符(波浪号) 前缀来避免这种行为.

修饰: 与普通热键不同的是, 自定义组合在默认情况下表现得就像拥有一个通配符(*) 修饰一样. 例如, 1 & 2:: 当按下 12 时, 无论 CtrlAlt 是否被按住都会触发, 然而 ^1:: 仅在 Ctrl+1 组合键时触发, 而 Ctrl+Alt+1 不会触发.

不支持组合三个或更多的键. 一般来说组合键支持你键盘上物理存在的所有按键, 都可以用 #IfGetKeyState() 探测状态, 但是也可能出现不一致的情况. 例如:

; 以任何顺序按下 AppsKey 和 Alt, 然后按下反斜杠键(/).
#if GetKeyState("AppsKey", "P")
Alt & /::MsgBox Hotkey activated.

; 如果对调 AppsKey 和 Alt, 则必须先按下 Alt(一次按一个):
#if GetKeyState("Alt", "P")
AppsKey & /::MsgBox Hotkey activated.

; 同时按下这三个键: [ & ] & \::
#if GetKeyState("[") && GetKeyState("]")
\::MsgBox

键盘钩子: 自定义的组合键总是使用键盘钩子, 如使用前缀键作为后缀的任何热键. 例如, a & b:: 导致 ^a:: 使用键盘钩子.

其他特性

NumLock, CapsLock 和 ScrollLock: 这些键可以被强制设置为 "AlwaysOn" 或 "AlwaysOff". 例如: SetNumLockState AlwaysOn.

覆盖资源管理器热键: 在脚本中可以为 Windows 内置的热键例如 Win+E(#e) 和 Win+R(#r) 指定一个动作来个别的替换. 请参阅覆盖页面了解详情.

替换 Alt-Tab: 热键可以提供 Alt-Tab 切换窗口的可选方法. 例如, 下面的两个热键可以让您用右手进行 alt-tab:

RControl & RShift::AltTab  ; 按住右 control 后接着反复下右 shift 来向前移动.
RControl & Enter::ShiftAltTab  ; 甚至不需要释放右 control, 直接按 Enter 来反向移动.

想了解更多细节, 请参阅 Alt-Tab.

鼠标滚轮热键

通过键名 WheelDown 和 WheelUp 可以支持转动滚轮来激发热键. 这里是一些鼠标滚轮热键的例子:

MButton & WheelDown::MsgBox You turned the mouse wheel down while holding down the middle button.
^!WheelUp::MsgBox You rotated the wheel up while holding down Control+Alt.

[v1.0.48+]: 也支持 WheelLeft 和 WheelRight, 但在早于 Windows Vista 的操作系统上没有效果. 有些鼠标只有一个滚轮, 可以向上或向下滚动或向左或向右倾斜. 通常, 在这些情况下, 将滚轮固定在一侧时会重复发送 WheelLeft 或 WheelRight 信号, 以模拟连续滚动. 这通常会导致热键重复执行.

[v1.0.43.03+]: 内置变量 A_EventInfo 包含了滚轮转动的格数, 通常为 1. 然而在后面的情况中, A_EventInfo 可能大于或小于 1:

鼠标滚轮最有用的一些热键包括滚动窗口文本的可选方法. 例如, 使用下面的一对热键可以在您按住左 Ctrl 并转动滚轮时进行水平滚动而不是垂直滚动:

~LControl & WheelUp::  ; 向左滚动.
ControlGetFocus, fcontrol, A
Loop 2  ; <-- 增加这个值来加快滚动速度.
    SendMessage, 0x0114, 0, 0, %fcontrol%, A  ; 0x0114 是 WM_HSCROLL, 它后面的 0 是 SB_LINELEFT.
return

~LControl & WheelDown::  ; 向右滚动.
ControlGetFocus, fcontrol, A
Loop 2  ; <-- 增加这个值来加快滚动速度.
    SendMessage, 0x0114, 1, 0, %fcontrol%, A  ; 0x0114 是 WM_HSCROLL, 它后面的 1 是 SB_LINERIGHT.
return

最后, 由于鼠标滚轮热键只产生按下事件(从没有弹起事件), 所以它们无法用作弹起的按键热键.

热键技巧和备注

根据 NumLock 的状态, 每个小键盘上的按键可以运行两个不同的热键子程序. 可选的, 可以让小键盘上的按键不论状态如何都运行相同的子程序. 例如:

NumpadEnd::
Numpad1::
MsgBox, This hotkey is launched regardless of whether NumLock is on.
return

如果波浪号(~)前缀键一起使用, 即使只是一次, 那么其中的前缀键总是会被发送到活动窗口. 例如, 在下面的两个热键中, 活动窗口都会接收到右键点击, 尽管只是其中一个热键使用了波浪号:

~RButton & LButton::MsgBox You pressed the left mouse button while holding down the right.
RButton & WheelUp::MsgBox You turned the mouse wheel up while holding down the right button.

Suspend 命令可以临时禁用所有的热键, 但不包括您要排除的那些. 要得到更大的选择性, 请使用 #IfWinActive/Exist.

通过使用 Hotkey 命令, 可以在脚本运行时动态创建热键. Hotkey 命令还能单独地修改, 禁用或启用脚本现有的热键.

控制器热键当前不支持修饰符前缀, 例如 ^(Ctrl) 和 #(Win). 不过, 您可以使用 GetKeyState 来模仿这种效果, 如下所示:

Joy2::
if not GetKeyState("Control")  ; 左边和右边的 Control 键都没有按下.
    return  ; 即什么都不做.
MsgBox You pressed the first controller's second button while holding down the Control key.
return

如果热键应该在继续执行前等待其修饰键被释放, 这可能需要一些时间. 请参考下面的例子:

^!s::Send {Delete}

按下 Ctrl+Alt+S 会让系统以为您按下了 Ctrl+Alt+Del(由于系统对此热键侵略性的检测). 要解决此问题, 请使用 KeyWait 来等待按键释放; 例如:

^!s::
KeyWait Control
KeyWait Alt
Send {Delete}
return

如果像 #z:: 这样的热键标签产生了类似 "无效热键" 的错误, 那么您的系统键盘布局/语言可能不包含特殊字符(此时为 "Z"). 尝试使用您键盘布局中您知道的其他字符.

热键标签可以作为 GosubGoto 的目标. 例如: Gosub ^!s. 有关详情, 请参阅标签.

热键的一个常见用途是启动和停止重复的动作, 例如一系列的键击或鼠标点击. 关于这方面的例子, 请参阅这个 FAQ 主题.

最后, 每个脚本都是准多线程的, 这样可以在之前的热键子程序还在运行时启动新的热键. 例如, 即使在当前热键显示消息框时也能启动新热键.

Alt-Tab 热键

Alt-Tab 热键简化了新组合键到系统 Alt-Tab 热键的映射, 它被用来调用切换任务(激活窗口) 的菜单.

每个 Alt-Tab 热键必须是一个键或两个键的组合, 通常通过和符号(&) 实现. 在下面的例子中, 按住右 Alt 然后按下 JK 来浏览 alt-tab 菜单:

RAlt & j::AltTab
RAlt & k::ShiftAltTab

AltTabShiftAltTab 是两个特殊的命令, 它们仅在与热键在同一行时才能被识别. 这里是完整的列表:

AltTab: 如果 alt-tab 菜单可见, 那么在菜单中前移. 否则, 显示菜单(仅当热键为两个按键的组合键时; 否则, 它什么都不做).

ShiftAltTab: 与上面相同, 不过这里在菜单中后移.

AltTabMenu: 显示或隐藏 alt-tab 菜单.

AltTabAndMenu: 如果 alt-tab 菜单可见, 那么在菜单中前移. 否则, 显示菜单.

AltTabMenuDismiss: 关闭 Alt-tab 菜单.

为了举例说明上述命令, 可以用鼠标滚轮完全代替 Alt-tab. 当下面的热键生效时, 点击鼠标中键显示菜单, 转动滚轮在菜单中导航:

MButton::AltTabMenu
WheelDown::AltTab
WheelUp::ShiftAltTab

要取消 Alt-Tab 菜单而不激活选择的窗口, 按下或发送 Esc. 在下面的例子中, 按住左 Ctrl 并按下 CapsLock 来显示菜单并在其中向前移动. 然后释放左 Ctrl 激活所选窗口, 或按下鼠标滚轮取消. 在运行这个例子之前, 定义 AltTabWindow 窗口组, 如下所示.

LCtrl & CapsLock::AltTab
#IfWinExist ahk_group AltTabWindow ; 表示 alt-tab 菜单出现在屏幕上.
*MButton::Send {Blind}{Escape} ; * 前缀允许它被触发, 无论 Alt 是否被按住.
#If

如果脚本发送 {Alt Down}(例如调用 Alt-Tab 菜单), 那么也可能需要发送 {Alt Up}, 如下面的例子所示.

一般说明

当前, 所有特殊的 Alt-tab 动作必须像上面的例子那样直接指定到热键上(即它们无法像命令那样使用). 它们不受 #IfWin#If 的影响.

无论是否使用 up 关键字, alt-tab 动作都可以在 key-down 和/或 key-up 生效, 并且不能与同一键上的其他动作相结合. 例如, 同时使用 F1::AltTabMenuF1 up::OtherAction() 是不支持的.

自定义的 alt-tab 动作还可以通过热键创建. 由于不同版本的操作系统对 alt-tab 菜单的标识不同, 使用如下所示的窗口组可能会有帮助. 在上面和下面例子中使用 ahk_group AltTabWindow, 这个窗口组是在脚本启动段定义的. 另外, ahk_group AltTabWindow 也可以用适合你的系统的 ahk_class 来代替.

GroupAdd AltTabWindow, ahk_class MultitaskingViewFrame  ; Windows 10
GroupAdd AltTabWindow, ahk_class TaskSwitcherWnd  ; Windows Vista, 7, 8.1
GroupAdd AltTabWindow, ahk_class #32771  ; 更早的系统, 或启用了经典的 alt-tab

在下面的例子中, 按下 F1 来显示菜单并向前移动. 然后可以按下 F2 来激活选择的窗口, 或按下 Esc 取消:

*F1::Send {Alt down}{tab} ; 这里需要星号.
!F2::Send {Alt up}  ; 释放 Alt 键激活选择的窗口.
#IfWinExist ahk_group AltTabWindow
~*Esc::Send {Alt up} ; 取消菜单时, 自动释放 Alt 键.
;*Esc::Send {Esc}{Alt up} ; 如果不使用(~), 则需要发送 Escape 键.
#If

函数热键[v1.1.20+]

紧跟在热键标签后面的函数, 通过简单的定义, 一个或多个热键可以关联到此函数, 如下例所示:

; Ctrl+Shift+O 在资源管理器中打开包含文件夹.
; Ctrl+Shift+E 打开文件夹并选中当前编辑文件.
; 支持 SciTE.
^+o::
^+e::
    editor_open_folder() {
        WinGetTitle, path, A
        if RegExMatch(path, "\*?\K(.*)\\[^\\]+(?= [-*] )", path)
            if (FileExist(path) && A_ThisHotkey = "^+e")
                Run explorer.exe /select`,"%path%"
            else
                Run explorer.exe "%path1%"
    }

[v1.1.28+]: 热字串也可以这样定义. 可以将多个热键或热字串组合在一起, 以调用相同的函数.

在热键/热字串标签和函数之间仅允许空白, 注释或者指令. 以这种方式定义的热键/热字串标签对 IsLabel(), Gosub 或其他命令是不可见的; 然而, 即使关联了函数, 自动执行段也会以第一个热键/热字串结束.

使用函数的的主要好处是可以使用局部变量, 当两个或多个热键为了不同的目的使用相同的变量名时, 避免了冲突. 它也鼓励自我记录热键, 就像上面的代码在函数内描述热键.

Hotkey 也可以关联函数或函数对象.