使用双冒号语法可以快速创建热键,简单、直接,非常方便。有时我们需要经常修改一些热键或把脚本给别人使用, 通常必须考虑把热键放在专门的配置中以方便修改,此时就需要动态实现热键了。
使用 Hotkey 命令
这个命令本身的用法简单,这里结合常见的具体场景介绍:
Code: Select all
; 为了简便这里直接赋值变量(实际情况中可从配置文件读取):
MyHotkey := "F1"
; 下面这个热键仅在记事本中有效:
Hotkey, IfWinActive, ahk_class Notepad
Hotkey, %MyHotkey%, MyLabel_1
; 下面这个热键为全局热键:
Hotkey, If
Hotkey, %MyHotkey%, MyLabel_2
; 下面这个热键在记事本或写字板窗口活动时有效:
Hotkey, If, WinActive("ahk_class Notepad") || WinActive("ahk_class WordPadClass")
Hotkey, %MyHotkey%, MyLabel_3
Return
; 这里使用不同的标签,是便于调试具体生效的是哪个变体:
MyLabel_1:
MyLabel_2:
MyLabel_3:
MsgBox, 您按下了 %A_ThisHotkey% 热键(%A_ThisLabel%)。
Return
; 上面的第三个热键需要该指令才起作用(注:这里的“||”替换为“or”无效):
#If, WinActive("ahk_class Notepad") || WinActive("ahk_class WordPadClass")
Code: Select all
Hotkey, IfWinActive, ahk_class Notepad
Code: Select all
Hotkey, IfWinActive
Code: Select all
Hotkey, IfWinActive, ahk_class Notepad
Hotkey, IfWinActive, ahk_class WordPadClass
Hotkey, %MyHotkey%, MyLabel_1
Code: Select all
Hotkey, If, WinActive("ahk_class Notepad") || WinActive("ahk_class WordPadClass")
Code: Select all
#If, WinActive("ahk_class Notepad") || WinActive("ahk_class WordPadClass")
关于热键优先级:一般而言,钩子热键优先级最高,最近启用的优先级更高,局部变体优先级高于全局变体(多个局部变体都有效时最先启用的优先级更高)。前面的有些结论可能仅适用于同一脚本而言,不同脚本及与其他程序之间实际情况比较复杂。
热键的优先级与启用顺序和作用范围有关,但先创建的并不总是高优先级。
双冒号热键和 Hotkey 创建的热键是分别管理的,后者是通过该命令的选项管理自身创建的热键,具体请参阅帮助。Hotkey 命令不能直接启用或禁用脚本中不是它创建的热键,但在大多数情况下它可以通过创建或启用相同的热键来覆盖它们。
使用 Input 命令
请用 AutoHotkey 实现按任意键继续的功能。
请思考,您会如何实现?很容易想到命令提示符中的 pause 命令,在批处理中执行某些操作前先提示用户,随意按某个键后继续执行,AutoHotkey 中应如何实现相同功能?也许实际中不一定需要,但思考可以锻炼思维。先看看我的实现:
Code: Select all
; 建立所有按键列表,尽管可能有些键未包含在其中,这里用于演示。
AllKeyList := "a|b|c|d|e|f|g|h|i|j|k|l|m|n|o|p|q|r|s|t|u|v|w|x|y|z|{LControl}|{RControl}|{LAlt}|{RAlt}|{LShift}|{RShift}|{LWin}|{RWin}|{AppsKey}|{F1}|{F2}|{F3}|{F4}|{F5}|{F6}|{F7}|{F8}|{F9}|{F10}|{F11}|{F12}|{Left}|{Right}|{Up}|{Down}|{Home}|{End}|{PgUp}|{PgDn}|{Del}|{Ins}|{BS}|{Capslock}|{Numlock}|{PrintScreen}|{Pause}"
Loop, Parse, AllKeyList, |
{
; 把 Send 参数中发送模拟按键的格式转成热键参数中的按键格式:
OneKey := Trim(A_LoopField, "{}")
Hotkey, ~%OneKey%, Operation
}
Return
Operation:
MsgBox, 您按下了 %A_ThisHotkey% 键。
Return
上面虽然实现了功能,不过从编写效率或移植角度看这种实现不好(如果都用双冒号会更糟糕),热键功能是 AutoHotkey 的特色,有更好的实现吗(其他脚本中蹩脚是正常的)?
Code: Select all
; 来自帮助(一行命令,干净简洁):
Input, SingleKey, L1, {LControl}{RControl}{LAlt}{RAlt}{LShift}{RShift}{LWin}{RWin}{AppsKey}{F1}{F2}{F3}{F4}{F5}{F6}{F7}{F8}{F9}{F10}{F11}{F12}{Left}{Right}{Up}{Down}{Home}{End}{PgUp}{PgDn}{Del}{Ins}{BS}{Capslock}{Numlock}{PrintScreen}{Pause}
; 需要注意,由于 SingleKey 只记录按键按下后生成的字符,所以产生不可见字符的按键应放在 EndKeys 参数中。
Code: Select all
Input, Code, C I L4, {Space}{Enter}{Esc} ; 码表式输入法核心示例。
说到这个命令,必须和大家分享一段代码,实现很精妙(原本想放到 AutoHotKey 常用函数或小技巧有哪些分享?上的,但可能不容易理解):
Code: Select all
; 节选自小众屏幕密码锁(http://www.appinn.com/lock-screen-appinn/)并做了简单调整
Key := "test"
i := 1
Loop ; 锁定后就一直处于循环状态,直到解锁
{
Input, a, L1
Temp := SubStr(Key, i, 1) ; 提取 Key 中第 i 位字符
If (a = Temp)
{
i++ ; 准备匹配下一位。
}
Else
{
i := 1 ; 重头开始匹配。
}
If (i= StrLen(Key) + 1) ; 输入匹配了,退出循环。
{
MsgBox, 您输入了正确的通行码。
Break
}
}
为什么不按下面这样实现?
Code: Select all
Key := "test"
i := 1
Loop
{
Input, a, % "L" StrLen(Key)
If (a = Key)
{
MsgBox, 您输入了正确的通行码。
Break
}
}
使用 A_PriorKey
上面没有提到,实际上使用 Input 是有局限性的,如不支持鼠标按键,而通过 A_PriorKey 不仅能检测到按键,还能检测到按钮(需要安装钩子):
Code: Select all
#InstallKeybdHook
#InstallMouseHook
Loop {
ToolTip % A_PriorKey
Sleep 100
}
小结
动态热键的用途不限于本文开头介绍的情况, 例如还可以快速创建大量热键。