【热键】让热键动起来

作者:amnesiac 首发:官方论坛中文版

引子:有些文章只看它的标题,您就看不出它的内容,则很可能错过它的精彩,本文即是其中一例。

使用双冒号语法可以快速创建热键,简单、直接,非常方便。有时我们需要经常修改一些热键或把脚本给别人使用, 通常必须考虑把热键放在专门的配置中以方便修改,此时就需要动态实现热键了。

使用 hotkey 命令

这个命令本身的用法简单,这里结合常见的具体场景介绍:

; 为了简便这里直接赋值变量(实际情况中可从配置文件读取):
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")

下面进行简单的分析:

Hotkey, IfWinActive, ahk_class Notepad

设置热键生效的窗口条件,可使用窗口存在/不存在/活动/不活动(IfWinActive/IfWinNotActive/IfWinExist/IfWinNotExist),效果等同于对应的系列指令(不过作用对象有区别,一个是双冒号热键,一个是 hotkey 热键)。

Hotkey, IfWinActive

取消热键条件,其中的 IfWinActive 可替换为 IfWinExist/IfWinNotActive/IfWinNotExist/If(注:这里还包括 If)。

Hotkey, IfWinActive, ahk_class Notepad
Hotkey, IfWinActive, ahk_class WordPadClass
Hotkey, %MyHotkey%, MyLabel_1

这种条件与对应指令类似,效果是互斥的,所以上面这个热键不会在记事本和写字板中都生效。

Hotkey, If, WinActive("ahk_class Notepad") || WinActive("ahk_class WordPadClass")

尽管这里的条件仍与窗口有关,不过实际上可以任意表达式,只需满足存在相应的 #If 指令且它们包含的表达式完全一致。

#If, WinActive("ahk_class Notepad") || WinActive("ahk_class WordPadClass")

原本 #If 指令是与位置有关,但由于这个脚本中没有双冒号热键和热字串,所以这里放在什么位置关系不大。

关于热键优先级:一般而言,钩子热键优先级最高,最近启用的优先级更高,局部变体优先级高于全局变体(多个局部变体都有效时最先启用的优先级更高)。前面的有些结论可能仅适用于同一脚本而言,不同脚本及与其他程序之间实际情况比较复杂。

热键的优先级与启用顺序和作用范围有关,但先创建的并不总是高优先级。

双冒号热键和 Hotkey 创建的热键是分别管理的,后者是通过该命令的选项管理自身创建的热键,具体请参阅帮助。Hotkey 命令不能直接启用或禁用脚本中不是它创建的热键,但在大多数情况下它可以通过创建或启用相同的热键来覆盖它们。

使用 Input 命令

请用 AutoHotkey 实现按任意键继续的功能。

请思考,您会如何实现?很容易想到命令提示符中的 pause 命令,在批处理中执行某些操作前先提示用户,随意按某个键后继续执行,AutoHotkey 中应如何实现相同功能?也许实际中不一定需要,但思考可以锻炼思维。先看看我的实现:

; 建立所有按键列表,尽管可能有些键未包含在其中,这里用于演示。
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

按任意键,就建立“任意键”的热键,思路很明确。现在要转换成“提示用户一些信息并按任意键继续”就简单了,加上一对 ToolTip(在该片段前加带参数的 ToolTip 而 Operation 子程序中加不带参数的)或使用类似的方法。

上面虽然实现了功能,不过从编写效率或移植角度看这种实现不好(如果都用双冒号会更糟糕),热键功能是 AutoHotkey 的特色,有更好的实现吗(其他脚本中蹩脚是正常的)?

; 来自帮助(一行命令,干净简洁):
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 参数中。

这里实际上创建了一批热键,比较而言,Hotkey 创建单个热键很方便,但创建批量热键时应优先考虑 Input。创建批量热键的一种典型的情况是类似码表式输入法,其中需要批量转译输入为对应的输出,一个码表(保存了输入字符组与输出字符组的对应关系),一个平台(脚本中实现转换功能),该平台中核心功能就是 Input:

Input, Code, C I L4, {Space}{Enter}{Esc} ; 码表式输入法核心示例。

例如五笔输入法的特点:最长四码,按空格键可输入一、二、三级简码。当然,实际情况比较复杂,需要处理全角、半角、标点符号和特殊按键,加上候选框就更复杂了。到这里,您理解我之前曾说热字串是序列键(热键的一种)吗?刚才谈论的功能和热字串本源上都是热键。

说到这个命令,必须和大家分享一段代码,实现很精妙(原本想放到 AutoHotKey 常用函数或小技巧有哪些分享?上的,但可能不容易理解):

; 节选自小众屏幕密码锁(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
    }
}

前面几句可能不好理解,我们考察开始的几次循环:i=1 时接受一位输入并与 Key 中的第一位比较,相同则 i 自增,否则继续从新开始。i=2 时(第一次的输入已经匹配 Key 中的第一位),继续接受输入一位与 Key 中的第二位比较……若连续 i 位都与 Key 中的第 i 位相同,即刚才输入的字符串已经完全匹配 Key。

为什么不按下面这样实现?

Key := "test"
i := 1
Loop
{
    Input, a, % "L" StrLen(Key)
    If (a = Key)
    {
        MsgBox, 您输入了正确的通行码。
        Break
    }
}

乍一看,他们的功能好像没什么区别,自己动动手比较吧(如果不实践,永远不会知道看起来正常的代码却不会按预期运行的原因)。另外,小众屏幕密码锁也是个很实用的功能,输入密码时别人看不到,也不容易猜出来(先输一些错的字符)。

使用 A_PriorKey

上面没有提到,实际上使用 Input 是有局限性的,如不支持鼠标按键,而通过 A_PriorKey 不仅能检测到按键,还能检测到按钮(需要安装钩子):

#InstallKeybdHook
#InstallMouseHook
Loop {
    ToolTip % A_PriorKey
    Sleep 100
} 

之前说到任意键,您意识到按钮了吗?

小结

动态热键的用途不限于本文开头介绍的情况, 例如还可以快速创建大量热键。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 205,033评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,725评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,473评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,846评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,848评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,691评论 1 282
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,053评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,700评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 42,856评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,676评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,787评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,430评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,034评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,990评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,218评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,174评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,526评论 2 343

推荐阅读更多精彩内容

  • 注:中文应用部分仍需更新。转者按:本文属于零基础入门专题教程,原发表于 Download!网络密技王第三期,后转载...
    amnesiac阅读 3,353评论 0 6
  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,598评论 18 139
  • linux资料总章2.1 1.0写的不好抱歉 但是2.0已经改了很多 但是错误还是无法避免 以后资料会慢慢更新 大...
    数据革命阅读 12,131评论 2 34
  • AutoHotkey是一个windows下的开源、免费、自动化软件工具。它由最初旨在提供键盘快捷键的脚本语言驱动(...
    晚晴幽草阅读 5,455评论 16 89
  • Ubuntu的发音 Ubuntu,源于非洲祖鲁人和科萨人的语言,发作 oo-boon-too 的音。了解发音是有意...
    萤火虫de梦阅读 99,138评论 9 467