热键(鼠标, 操纵杆和键盘快捷键)

AutoHotKey

热键(鼠标, 操纵杆和键盘快捷键)

目录

入门和简单示例

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

#n::
Run Notepad
return

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

#n::Run Notepad

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

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

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

符号 说明
# Win (Windows 徽标键). 在 v1.0.48.01+, 对于 Windows Vista 及以上版本, 包含 Windows 键的热键 (例如 #a) 会等待 Windows 键被释放后才发送任何包含 "L" 键击的文本. 这样避免了这种热键中的 Send 锁定 PC. 这种行为适用于除 SendPlay (这里不需要) 和 盲从模式 外的所有发送模式.
! Alt
^ Control
+ Shift
& 和符号可以用来组合任意两个按键或鼠标按钮, 让它们成为自定义热键. 请参阅 后面 了解详情.
< 使用成对按键中左边的那个. 例如 <!a 相当于 !a, 只是使用左边的 Alt 键才可以触发.
> 使用成对按键中右边的那个.
<^>!

AltGr (alternate graving). 如果您键盘布局中含 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 组合键的时候.

如果波浪号前缀应用于自定义组合而非不可组合键, 按键的原生功能将持续锁定. 例如, 下面的脚本, 按住 AppsKey 键将会一直显示一个 ToolTip 而不会触发上下文菜单:

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 可以跟在热键名后面使得在释放按键时触发热键, 而不是按下时. 下面的例子把 LWin 重映射 为 LControl:

*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

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

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")
WheelUp::Send {Volume_Up}     ; 在任务栏上滚动滚轮:增加/减小音量.
WheelDown::Send {Volume_Down} ;

自定义组合

通过在两个按键 (不包括操纵杆按钮) 间使用 "&" 可以定义定制的组合键. 在下面的例子中, 您在按住 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:: 无论 Ctrl 或 Alt 是否被按住都会触发, 然而 ^1:: 仅在 Ctrl+1 组合键时触发, 而 Ctrl+Alt+1 不会触发.

对于普通的修饰键, 一般的热键会比 "自定义" 组合工作得更好. 例如, <+s:: 就是比 LShift & s:: 更好的用法.

不支持组合三个或更多的键. 一般来说组合键支持你键盘上物理存在的所有按键, 都可以用 #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 可以支持转动滚轮来激发热键. 在 v1.0.48+ 中还支持 WheelLeft 和 WheelRight, 但在早于 Windows Vista 的操作系统上没有效果. 这里是一些鼠标滚轮热键的例子:

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.43.03+, 内置变量 A_EventInfo 包含了滚轮转动的格数, 通常为 1. 然而在后面的情况中, A_EventInfo 可能大于或小于 1:

  • 如果鼠标硬件报告小于一格的距离, 那么 A_EventInfo 可能为 0;
  • 如果快速滚动滚轮 (取决于鼠标类型), 那么 A_EventInfo 可能大于 1. 像后面这样的热键可以帮助您分析鼠标:~WheelDown::ToolTip %A_EventInfo%.

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

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

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

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

热键技巧和备注

根据 Numlock的状态, 每个小键盘上的按键可以运行两个不同的热键子程序. 可选的, 可以让小键盘上的按键不论 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 命令还能单独地修改, 禁用或启用脚本现有的热键.

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

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

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

^!s::Send {Delete}

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

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

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

热键标签可以作为 GosubGoto 的目标. 例如:Gosub ^!s.

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

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

Alt-Tab 热键

每个 Alt-Tab 热键必须是两个键的组合, 通常通过和符号 (&) 实现. 在下面的例子中, 按住右 Alt 键并按下 J 或 K 可以导航 alt-tab 菜单:

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

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

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

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

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

AltTabMenuDismiss: 关闭 Alt-tab 菜单.

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

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

要取消热键调用的 Alt-tab 菜单而不激活选择的窗口, 请使用类似下面这样的热键:它可能需要根据后面的这些进行调整: 1) 最初显示 alt-tab 菜单的方法; 和 2) 脚本是否安装了 键盘钩子.

LCtrl & CapsLock::AltTab
!MButton::  ; 鼠标中键. ! 前缀让它在按住 Alt 键时激发 (当 alt-tab 菜单可见时, alt 键是按住的).
IfWinExist ahk_class #32771  ; 表示 alt-tab 菜单出现在屏幕上.
    Send !{Escape}{Alt up}
return

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

自定义的 alt-tab 动作还可以通过热键创建. 在下面的例子中, 按下 F1 来显示菜单并预先向前移动. 然后可以按下 F2 来激活选择的窗口 (或按下 Escape 取消):

*F1::Send {Alt down}{tab} ; 这里需要星号.
!F2::Send {Alt up}  ; 释放 Alt 键激活选择的窗口.
~*Escape::
IfWinExist ahk_class #32771
    Send {Escape}{Alt up}  ; 取消菜单而不激活选择的窗口.
return

函数热键[v1.1.20+]

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

; Ctrl+Shift+O to open containing folder in Explorer.
; Ctrl+Shift+E在资源管理器中定位当前编辑文件.
; 支持SciTE和Notepad++.
^+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%"
    }

在热键标签或者标签和函数之间仅允许空白, 注释或者指令. 没有热键的标签被创建通过这种定义方式; 然而 自动执行段 结束再第一个热键就算关联了函数.

这种方式的主要好处是可以使用局部变量从而避免两个或两个以上的热键使用相同的变量名. 它也鼓励自我记录热键就像上面的代码在函数内描述热键.

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