创建一个对象, 该对象可用于收集或拦截键盘输入.
InputHookObj := InputHook(Options, EndKeys, MatchList)
类型: 字符串
由零个或多个下列选项组成的字符串(可任意顺序, 中间可选空格):
B: 设置 BackspaceIsUndo 为 0(false), 这会导致 Backspace 被忽略.
C: 设置 CaseSensitive 为 1(true), 使 MatchList 区分大小写.
I: 设置 MinSendLevel 为 1 或给定值, 使任何输入级别低于该值的输入被忽略. 例如, I2
将忽略级别为 0(默认值) 或 1 的任何输入, 但将捕获级别为 2 的输入.
L: 长度限制(例如 L5
). 输入的最大允许长度. 当文本达到这个长度时, 输入被终止, EndReason 被设置为单词 Max(除非文本匹配 MatchList 中的一个短语, 在这种情况下 EndReason 被设置为单词 Match). 如果未指定, 则长度限制为 1023.
指定 L0
禁用文本的收集和长度限制, 但并不影响按键生成的文本的统计(请参阅 VisibleText). 这可以与 OnChar, OnKeyDown, KeyOpt 或 EndKeys 参数组合使用.
M: 允许在更大范围内使修饰键击生成文本. 通常情况下, 除了 Shift, Ctrl+Alt(即 AltGr) 或 Ctrl+Alt+Shift(即 AltGr+Shift), 按键和其他修饰键组合将被视为非文本. 该选项会尝试翻译其他修饰键组合. 参考这个例子, 它识别 Ctrl+C:
CtrlC := Chr(3) ; 将 Ctrl-C 对应的字符存储在 CtrlC 变量中. ih := InputHook("L1 M") ih.Start() ih.Wait() if (ih.Input = CtrlC) MsgBox "You pressed Control-C."
默认情况下, 系统将 Ctrl+A 到 Ctrl+Z 映射为 ASCII 控制字符 Chr(1) 到 Chr(26). 系统或活动窗口的键盘布局可定义其他转换. 对于键盘布局未定义修饰符位掩码的修饰符键, 转换可能会忽略. 例如, 如果使用 M 选项, Win+E 通常会转写为 "e".
M 选项可能会导致某些键盘快捷键, 如 Ctrl+← 在 Input 正在进行时出现异常.
T: 设置 Timeout (例如 T3
或 T2.5
).
V: 设置 VisibleText 和 VisibleNonText 为 1(true). 通常, 用户的输入被阻止(对系统隐藏). 使用此选项可将用户的击键发送到活动窗口.
*: 通配符. 设置 FindAnywhere 为 1(true), 允许在用户键入的任何位置找到匹配项.
E: 按字符代码而不是键码处理单字符结束键. 如果活动窗口的键盘布局与脚本的键盘布局不同, 则可以提供更一致的结果. 它还可以防止实际上不会产生给定结束字符的键组合结束 Input(输入); 例如, 如果 @ 是结束键, 则在美式键盘中 Shift+2 将触发它, 但 Ctrl+Shift+2 不会触发(在使用 E 选项时). 如果还使用 C 选项, 则结束字符区分大小写.
类型: 字符串
一个由零个或多个按键组成的列表, 其中任何一个键在按下时终止输入(结束键本身不会写入输入缓冲). 当 Input 以这种方式终止时, EndReason 设置为单词 EndKey, EndKey 属性设置为键的名称.
EndKeys 使用类似于 Send 函数的格式. 例如, 指定 {Enter}.{Esc}
将使 Enter, . 或 Esc 任一一个都能终止 Input. 使用大括号本身作为结束键, 指定 {{}
和/或 {}}
.
要使用 Ctrl, Alt 或 Shift 作为结束键, 请指定键的左和/或右的版本, 而不是中性版本. 例如, 指定 {LControl}{RControl}
而不是 {Control}
.
尽管不支持诸如 Alt+C(!c) 这样的修饰键, 而非-字母数字字符(如 ?!:@&{}
) 默认情况下需要 Shift 或 AltGr 按键按下与否, 取决于字符的正常输入方式. 如果有 E 选项, 则将单个字符键名解释为字符, 在这种情况下, 修饰符键必须处于正确的状态才能生成该字符. 当同时使用 E 选项和 M 选项时, 通过在 EndKeys 中包括相应的 ASCII 控制字符来支持 Ctrl+A 到 Ctrl+Z.
还可以指定明确的虚拟按键代码, 例如 {vkFF}
或 {sc001}
. 这在键没有名称且按下时不产生可见字符的罕见情况下非常有用. 它的键码可以通过按键列表页面底部的步骤来确定.
类型: 字符串
以逗号分隔的关键词列表, 其中任何一个都将导致终止输入(在这种情况下, EndReason 将被设置为单词 Match). 用户输入的内容必须完全匹配匹配列表中的某个词组(除非有 * 选项). 此外, 分隔符逗号周围的任何空格或制表符都是有意义的, 这意味着它们是匹配字符串的一部分. 例如, 如果 MatchList 为 ABC , XYZ
, 则用户必须在 ABC 之后或 XYZ 之前键入空格以形成匹配.
两个连续的逗号产生单个原义逗号. 例如, 后面的匹配列表会在 string1 的末尾产生单个原义逗号: string1,,,string2
. 类似的, 后面的匹配列表仅包含其中有一个原义逗号的单个项目: single,,item
.
因为 MatchList 中的项目不被视为单独的参数, 所以列表可以完全包含在一个变量中. 事实上, 如果此列表的长度超过 16383, 那么列表的全部或部分必须包含在变量中, 因为这个长度是任何脚本行的最大长度. 例如, MatchList 可能由 List1 "," List2 "," List3
组成 -- 其中每个变量都包含匹配词组的子列表.
任何数量的 InputHook 对象都可以在任何时候创建和进行, 但是它们启动的顺序会影响 Input 的收集方式.
当每个 Input 开始时(通过 Start 方法), 它被推到堆栈的顶部, 只有当 Input 终止时才从堆栈中删除. 键盘事件按最近开始到最早的顺序传递给每个输入. 如果一个输入抑制了一个给定的键盘事件, 那么它就不会再向下传递.
如果击键的发送级别低于 InputHook 的 MinSendLevel, 则忽略 Sent 的击键. 在这种情况下, 击键仍然可以由堆栈中较低的输入来处理.
多个 InputHook 都可以与 MinSendLevel 一起使用, 以分别收集发送的击键和实际击键.
InputHook 函数返回一个 InputHook 对象, 该对象具有以下方法和属性.
"InputHookObj" 在下面用作任何 InputHook 对象的占位符, 因为 "InputHook" 是类本身.
设置按键或按键列表的选项.
InputHookObj.KeyOpt(Keys, KeyOptions)
类型: 字符串
按键列表. 大括号用于括起按键名称, 虚拟键码或扫描码, 类似于 Send 函数. 例如, {Enter}.{{}
将应用于 Enter, . 和 {. 按名称, 按 {vkNN}
或按 {scNNN}
指定按键可能会产生三种不同的结果; 有关详情, 请参阅下文.
单独指定字符串 {All}
(不区分大小写) 以便将 KeyOptions 应用于所有 VK 和所有 SC, including {vkE7}
and {sc000}
as described below. 然后可以再次调用 KeyOpt 从特定按键中删除选项.
指定 {sc000}
将 KeyOptions 应用于所有缺乏扫描码的事件.
指定 {vkE7}
将 KeyOptions 应用于 Unicode 事件, 例如由 SendEvent "{U+221e}"
或 SendEvent "{Text}∞"
发送的事件.
类型: 字符串
下列单字符选项中的一个或多个(空格和制表符).
-(减号): 移除 -
后面的任何选项, 直到下一个 +
.
+(加号): 取消任何先前的 -
, 否则无效.
E: 结束键. 如果启用, 则按下键终止 Input, 将 EndReason 设置为单词 EndKey, 将 EndKey 设置为键的标准名称. 与 EndKeys 参数不同, Shift 或 AltGr 键的状态将被忽略. 例如, @
和 2
在美式键盘布局中都相当于 {vk32}
.
I: 忽略文本. 通常由该键生成的任何文本都将被忽略, 并且该键被视为非文本键(请参阅 VisibleNonText). 如果键通常不产生文本, 则没有效果.
N: 通知. 在每次按下键时调用 OnKeyDown 和 OnKeyUp 回调.
S: 处理按键后抑制(阻止) 按键. 这将覆盖 VisibleText 或 VisibleNonText 直到使用 -S
. +S
意味着 -V
.
V: 可见. 防止按键被抑制(阻止). 这将覆盖 VisibleText 或 VisibleNonText 直到使用 -V
. +V
意味着 -S
.
选项可以通过虚拟键码和扫描码来设置, 并且是累加的.
当按名称指定一个键时, 选项通过 VK 或 SC 来设置. 如果两个物理键共享相同的 VK, 但 SC 不同(如 Up 和 NumpadUp), 则由 SC 处理. 相反, 如果使用 VK 码, 则它将应用于产生该 VK 的任何物理键(这可能会随着时间的推移而变化, 这取决于活动键盘布局).
通过 VK 码删除选项不会影响 SC 设置的任何选项, 反之亦然. 但是, 当按键名删除一个选项并且该名称由 VK 处理时, 对应的 SC 也会删除该选项(根据脚本的键盘布局). 这允许在对所有按键应用一个选项后按名称排除按键.
为了防止一个选项影响按键, 必须从该按键的 VK 和 SC 中删除该选项, 或 sc000 如果按键没有 SC.
Unicode 事件, 例如由 SendEvent "{U+221e}"
或 SendEvent "{Text}∞"
发送的事件, 会受到 vkE7 或 sc000 设置的选项的影响. 应用于 {All} 的任何选项都将应用于 vkE7 和 sc000, 因此要排除 Unicode 事件, 请从两者中删除该选项. 例如:
InputHookObj.KeyOpt("{All}", "+I") ; 忽略任何事件产生的文本 InputHookObj.KeyOpt("{vkE7}{sc000}", "-I") ; Unicode 事件除外.
启动收集输入.
InputHookObj.Start()
如果 Input 已经在进行中, 则没有效果.
新启动的 Input 放在 InputHook 堆栈的顶部, 这允许它覆盖任何先前启动的 Input.
此方法安装键盘钩子(如果还没有安装).
等待, 直到 Input 终止(InProgress 为 false).
EndReason := InputHookObj.Wait(MaxTime)
类型: 浮点数
如果省略, 将无期限等待. 否则, 请指定等待的最大秒数. 如果 Input 在 MaxTime 秒后仍在进行中, 则该方法返回且不终止 Input.
类型: 字符串
此方法返回 EndReason.
返回结束键的名称, 按下结束键以终止 Input.
KeyName := InputHookObj.EndKey
注意, EndKey 返回按键的 "标准" 名称, 而不管它在 EndKeys 参数中是如何编写的. 例如, {Esc}
和 {vk1B}
都产生 Escape
. GetKeyName 可用于检索标准名称.
如果使用 E 选项, EndKey 返回输入的实际字符(如果合适). 否则, 键名将根据脚本的活动键盘布局来确定.
如果 EndReason 不是 "EndKey", EndKey 返回一个空字符串.
返回在 Input 终止时逻辑上按下的修饰符的字符串.
Mods := InputHookObj.EndMods
如果所有修饰符在逻辑上都是按下的, 则完整的字符串为:
<^>^<!>!<+>+<#>#
这些修饰符与热键的具有相同的含义. 每个修饰符总是用 <(左) 或 >(右) 限定. 对应的键名是: LCtrl, RCtrl, LAlt, RAlt, LShift, RShift, LWin, RWin.
InStr 可以用来检查给定的修饰符(如 >!
或 ^
) 是否存在的. 下面的行可以用来将 Mods 转换成中性修饰符的字符串, 如 ^!+#
:
Mods := RegExReplace(Mods, "[<>](.)(?:>\1)?", "$1")
由于这是瞬间发生的, 此属性可能比 GetKeyState 更可靠, 即使在 Input 终止后立即调用 GetKeyState, 或者在 OnEnd 回调中.
返回 EndReason 字符串, 该字符串表明了 Input 是如何终止的.
Reason := InputHookObj.EndReason
如果 Input 正在进行, 则返回空字符串.
如果输入正在进行, 返回 1(true), 否则返回 0(false).
Boolean := InputHookObj.InProgress
返回自上次 Input 启动以来收集的任何文本.
String := InputHookObj.Input
此属性可在输入进行中或输入结束后使用.
返回导致 Input 终止的 MatchList 项目.
String := InputHookObj.Match
此属性返回匹配项(原始的大小写), 如果省略了 C 选项, 则返回的大小写可能与用户键入的大小写不同. 如果 EndReason 不是 "Match", 则返回空字符串.
检索或设置在 Input 终止时调用的函数对象.
MyCallback := InputHookObj.OnEnd
InputHookObj.OnEnd := MyCallback
MyCallback 是要调用的函数对象. 空字符串意味着没有函数对象.
回调接受一个参数, 定义如下:
MyCallback(InputHookObj) { ...
尽管为参数指定的名称无关紧要, 但它被赋值了一个对 InputHook 对象的引用.
如果不需要相应的信息, 可以省略回调的参数, 但在这种情况下必须指定星号, 例如 MyCallback(*)
.
该函数作为一个新线程被调用, 因此使用 SendMode 和 DetectHiddenWindows 等设置的默认值重新开始.
检索或设置将字符添加到输入缓冲后调用的函数对象.
MyCallback := InputHookObj.OnChar
InputHookObj.OnChar := MyCallback
MyCallback 是要调用的函数对象. 空字符串意味着没有函数对象.
回调接受两个参数, 定义如下:
MyCallback(InputHookObj, Char) { ...
尽管为参数指定的名称无关紧要, 以下值依次赋值给它们:
如果不需要相应的信息, 你可以从回调函数参数列表的末尾省略一个或多个参数, 但在这种情况下, 必须指定星号作为最后一个参数, 例如 MyCallback(Param1, *)
.
多个字符的存在表明在先前最后的键击中使用了一个死键, 但是这两个键不能转换为单个字符. 例如, 在一些键盘布局中 `e 产生 è
, 而 `z 产生 `z
.
当按下结束键时, 该函数不会被调用.
检索或设置当按下启用通知的按键时调用的函数对象.
MyCallback := InputHookObj.OnKeyDown
InputHookObj.OnKeyDown := MyCallback
键-按下通知必须首先由 KeyOpt 或 NotifyNonText 启用.
MyCallback 是要调用的函数对象. 空字符串表示没有函数对象.
回调函数接受三个参数, 可以定义如下:
MyCallback(InputHookObj, VK, SC) { ...
虽然你给参数的名字并不重要, 但是下面的值会依次赋值给它们:
如果不需要相应的信息, 你可以从回调参数列表的末尾省略一个或多个参数, 但在这种情况下, 必须指定星号作为最后一个参数, 例如 MyCallback(Param1, *)
.
要检索按键名称(如果有), 请使用 GetKeyName(Format("vk{:x}sc{:x}", VK, SC))
.
该函数作为一个新线程被调用, 因此使用设置(如 SendMode 和 DetectHiddenWindows) 的默认值重新开始.
当按下结束键时, 该函数不会被调用.
检索或设置释放启用通知的按键时调用的函数对象.
MyCallback := InputHookObj.OnKeyUp
InputHookObj.OnKeyUp := MyCallback
按键-释放通知必须首先由 KeyOpt 或 NotifyNonText 启用. 键被认为是文本还是非文本取决于什么时候键被按下. 如果 InputHook 在没有检测到 key-down 的情况下检测到 key-up, 则认为它是非文本.
MyCallback 是要调用的函数对象. 空字符串意味着没有函数对象.
回调函数接受三个参数, 可以定义如下:
MyCallback(InputHookObj, VK, SC) { ...
虽然你给参数的名字并不重要, 但是下面的值会依次赋值给它们:
如果不需要相应的信息, 你可以从回调参数列表的末尾省略一个或多个参数, 但是在这种情况下, 必须将星号指定为最后一个参数, 例如 MyCallback(Param1, *)
.
要检索按键名称(如果有), 请使用 GetKeyName(Format("vk{:x}sc{:x}", VK, SC))
.
该函数作为一个新线程, 调用, 因此使用设置(如 SendMode 和 DetectHiddenWindows) 的默认值重新开始.
控制 Backspace 是否从 Input 缓冲的末尾删除最近按下的字符.
CurrentSetting := InputHookObj.BackspaceIsUndo
InputHookObj.BackspaceIsUndo := NewSetting
如果已经赋值, CurrentSetting 为 NewSetting, 否则默认为 1(true), 除非被 B 选项覆盖.
NewSetting 是一个布尔值, 用于启用或禁用此设置.
当 Backspace 用作 undo 时, 它被视为文本输入键. 具体来说, 是否抑制该键取决于 VisibleText 而不是 VisibleNonText.
Backspace 与修饰符键(如 Ctrl) 结合使用, 则始终忽略 Backspace(检查的是修饰符的逻辑状态, 而不是物理状态).
注意: 如果输入文本是可见的(如在编辑器中) 并且使用箭头键或其他方法在其中导航, Backspace 仍然会删除最后一个字符, 而不是插入符号(插入点) 后面的字符.
控制 MatchList 是否区分大小写.
CurrentSetting := InputHookObj.CaseSensitive
InputHookObj.CaseSensitive := NewSetting
如果已经赋值, CurrentSetting 为 NewSetting, 否则默认为 0(false), 除非被 C 选项覆盖.
NewSetting 是一个布尔值, 用于启用或禁用此设置.
控制每个匹配项是否可以是输入文本的子字符串.
CurrentSetting := InputHookObj.FindAnywhere
InputHookObj.FindAnywhere := NewSetting
如果已经赋值, CurrentSetting 为 NewSetting, 否则默认为 0(false), 除非被 * 选项覆盖.
NewSetting 是一个布尔值, 用于启用或禁用此设置. 如果为真(true), 则可以在用户键入的任何位置找到匹配(匹配可以是输入文本的子字符串). 如果为假(false), 则用户键入的所有内容必须与 MatchList 中的一个短语匹配. 在这两种情况下, 都必须完整输入 MatchList 中的一个短语.
检索或设置要收集输入的最小发送级别.
CurrentLevel := InputHookObj.MinSendLevel
InputHookObj.MinSendLevel := NewLevel
如果已经赋值, CurrentSetting 为 NewSetting, 否则默认为 0, 除非被 I 选项覆盖.
NewLevel 应该是 0 到 101 之间的整数. 发送级别 低于 此值的事件将被忽略. 例如, 值 101 会忽略 SendEvent 生成的所有输入, 而值 1 只会忽略默认发送级别(0) 的输入.
无论这个设置如何, SendInput 和 SendPlay 方法总是被忽略. 除了 AutoHotkey 以外的任何其他源生成的输入都不会因为这个设置而被忽略.
控制当按下非文本键时是否调用 OnKeyDown 和 OnKeyUp 回调.
CurrentSetting := InputHookObj.NotifyNonText
InputHookObj.NotifyNonText := NewSetting
如果已经赋值, CurrentSetting 为 NewSetting, 否则默认为 0(false).
NewSetting 是一个布尔值, 用于启用或禁用此设置. 如果为 true, 可启用所有不产生文本的按键的通知, 如按下 ← 或 Alt+F. 设置此属性不会影响按键的 options, 因为文本的生成取决于按下按键时活动窗口的键盘布局.
NotifyNonText 通过考虑先前匹配的 VK 码的 key-down 是被归类为文本还是非文本来应用 key-up 事件. 例如, 如果 NotifyNonText 为 true, 那么按下 Ctrl+A 将同时产生对 Ctrl 和 A 的 OnKeyDown 和 OnKeyUp 调用, 而按下 A 本身不会调用 OnKeyDown 或 OnKeyUp, 除非使用 KeyOpt 来启用该键的通知.
有关计为生成文本的键详细信息, 请参阅 VisibleText.
检索或设置超时值(以秒为单位).
CurrentSeconds := InputHookObj.Timeout
InputHookObj.Timeout := NewSeconds
如果已经赋值, CurrentSetting 为 NewSetting, 否则默认为 0, 除非被 T 选项覆盖.
NewSeconds 是一个表示超时的浮点数. 0 意味着没有超时.
超时周期通常在调用 Start 时启动, 但如果在 Input 进行中为该属性赋值, 则会重新启动. 如果在超时时间过去后 Input 仍在进行中, 则终止输入并将 EndReason 设置为单词 Timeout.
控制不产生文本的键或键组合是否可见(不阻止).
CurrentSetting := InputHookObj.VisibleNonText
InputHookObj.VisibleNonText := NewSetting
如果已经赋值, CurrentSetting 为 NewSetting, 否则默认为 1(true). V 选项设置改选项为 1(true).
NewSetting 是一个布尔值, 用于启用或禁用此设置. 如果为真, 不产生文本的键和键组合可能触发热键或被传递到活动窗口. 如果为假, 则会阻止它们.
有关计为生成文本的键详细信息, 请参阅 VisibleText.
控制产生文本的键或键组合是否可见(不阻止).
CurrentSetting := InputHookObj.VisibleText
InputHookObj.VisibleText := NewSetting
如果已经赋值, CurrentSetting 为 NewSetting, 否则默认为 0(false), 除非被 V option.
NewSetting 是一个布尔值, 用于启用或禁用此设置. 如果为真(true), 产生文本的键和键组合可以触发热键或被传递到活动窗口. 如果为假(false), 则会阻止它们.
导致文本被附加到输入缓冲的任何击键都被视为生成文本, 即使在其他应用程序中通常不会这样做. 例如, 如果使用 M 选项, Ctrl+A 生成文本, 而 Esc 生成控制字符 Chr(27)
.
尽管死键通常不会立即产生效果, 但它们被视为产生文本. 按下死键也可能导致后面的键生成文本(如果只有死键的字符).
Backspace 仅在作为撤销时才被计为生成文本.
标准的修饰符键和 CapsLock, NumLock 和 ScrollLock 总是可见的(不被阻止).
EndReason 属性返回以下字符串之一:
字符串 | 描述 |
---|---|
Stopped | Stop 方法已被调用或 Start 方法尚未被调用. |
Max | 输入达到允许的最大长度, 且它不匹配 MatchList 中的任何项. |
Timeout | Input 超时. |
Match | Input(输入) 匹配 MatchList 中的一项. Match 属性包含匹配的项. |
EndKey |
EndKeys 中的一个被按下终止了输入. EndKey 属性包含终止键的名称或字符, 不带大括号. |
如果 Input(输入) 正在进行中, EndReason 为空. |
必须先调用 Start 方法, 然后才能收集输入.
InputHook 设计为允许脚本的不同部分都能监视输入, 并且冲突最小. 它可以连续操作, 例如观察任意的单词或其他模式. 它还可以临时运行, 例如收集用户输入或临时覆盖特定(或非-特定) 按键而不干扰热键.
当 Input 正在进行时, 键盘热键仍然有效, 但是如果任何必需的修饰符键被抑制, 或者如果热键使用 reg 方法并且其后缀键被抑制, 则不能激活热键. 例如, 热键 ^+a::
可能 会被 InputHook 覆盖, 而热键 $^+a::
会优先, 除非 InputHook 抑制 Ctrl 或 Shift.
按键抑制(阻止) 与否取决于以下因素(按顺序):
Input 正在进行时需要键盘钩子, 但当 Input 终止时, 如果不再需要键盘钩子, 则会自动卸载.
Input 正在进行时, 脚本为自动持续运行, 所以即使没有正在运行的线程, 它也会继续监视输入. 当输入结束时, 脚本可能会自动退出(如果没有正在运行的线程, 并且该脚本由于其他原因而不会持续运行).
AutoHotkey 不支持输入法编辑器(IME). 键盘钩子拦截键盘事件, 并通过使用 ToUnicodeEx 或 ToAsciiEx 将它们转换为文本(VK_PACKET 事件除外, 它封装了单个字符).
如果您使用多种语言或键盘布局, 则 InputHook 会使用活动窗口的键盘布局而不是脚本的(不论 Input 是否可见).
尽管不够灵活, 但热字串更容易使用.
在 AutoHotkey v1.1 中, InputHook 是 Input 命令的替代品, 提供了更大的灵活性. 在 2.0 版本中删除了 Input 命令, 但下面的代码基本相同:
; Input OutputVar, % Options, % EndKeys, % MatchList ; v1 ih := InputHook(Options, EndKeys, MatchList) ih.Start() ErrorLevel := ih.Wait() if (ErrorLevel = "EndKey") ErrorLevel .= ":" ih.EndKey OutputVar := ih.Input
Input 命令终止任何先前由它启动的 Input, 而 InputHook 允许同时多个 Input.
Options 解释相同, 但默认设置不同:
Input 命令在进行时会阻塞线程, 而 InputHook 允许线程继续, 甚至退出(这允许中断的任何线程继续运行). 脚本可以注册一个 OnEnd 函数, 当输入终止时调用该函数, 而不是等待.
Input 命令只在输入终止后返回用户的输入, 而 InputHook 的 Input 属性允许在任何时候检索它. 脚本可以注册一个 OnChar 函数, 以便在字符增加时调用, 而不是不断地检查 Input 属性.
InputHook 通过 KeyOpt 方法对单个按键提供了更多控制. 这包括添加或删除结束键, 抑制或不抑制特定键, 或忽略特定键生成的文本.
与 Input 命令不同, InputHook 可用于检测不产生文本的键, 而 不 终止输入. 这是通过注册 OnKeyDown 函数和使用 KeyOpt 或 NotifyNonText 来指定相关键来完成的.
如果 MatchList 中的项目导致 Input 终止, 可以参考 Match 属性来确定到底是哪个匹配(当 * 选项存在时这更有用).
尽管脚本可以在 Input 函数返回后查询 GetKeyState, 但有时它无法准确反映输入终止时按下了哪些键. InputHook 的 EndMods 属性反映了 Input 终止时修饰键的逻辑状态.
在向后兼容性方面有一些不同之处:
如果 EndKeys 中使用的键的名称对应于两个物理键共享 VK(如 NumpadUp 和 Up), 则 Input 命令通过 VK 处理主键通过 SC 处理次要键, 而 InputHook 都通过 SC 来处理. {vkNN}
表示可以通过 VK 来处理按键.
当结束键由 VK 处理时, 两个物理键都可以终止输入. 例如, {NumpadUp}
将导致通过按下 Up 终止 Input 命令, 但是 ErrorLevel 将包含 EndKey:NumpadUp
, 因为只考虑 VK.
当结束键由 SC 处理时, Input 命令将始终为任何给定 VK 的已知辅助 SC 生成名称, 并始终为任何其他键生成 scNNN
. 与之相比, InputHook 产生按键名(如果有).
KeyWait, 热字串, InputBox, InstallKeybdHook, 线程
MsgBox KeyWaitAny() ; 再来一遍, 但不阻止按键. MsgBox KeyWaitAny("V") KeyWaitAny(Options:="") { ih := InputHook(Options) if !InStr(Options, "V") ih.VisibleNonText := false ih.KeyOpt("{All}", "E") ; 结束 ih.Start() ih.Wait() return ih.EndKey ; 返回按键名称 }
等待任何与 Ctrl/Alt/Shift/Win 组合的按键.
MsgBox KeyWaitCombo() KeyWaitCombo(Options:="") { ih := InputHook(Options) if !InStr(Options, "V") ih.VisibleNonText := false ih.KeyOpt("{All}", "E") ; 结束 ; Exclude the modifiers ih.KeyOpt("{LCtrl}{RCtrl}{LAlt}{RAlt}{LShift}{RShift}{LWin}{RWin}", "-E") ih.Start() ih.Wait() return ih.EndMods . ih.EndKey ; 返回字符串, 例如 <^<+Esc }
简单的自动完成: 一周中的任何一天. 除了字母双关外, 这是一个功能齐全的例子. 只需运行脚本并开始输入, 按 Tab 完成或按 Esc 退出.
global WordList := "Monday`nTuesday`nWednesday`nThursday`nFriday`nSaturday`nSunday" global Suffix := "", SacHook SacHook := InputHook("V", "{Esc}") SacHook.OnChar := SacChar SacHook.OnKeyDown := SacKeyDown SacHook.KeyOpt("{Backspace}", "N") SacHook.Start() SacChar(ih, char) ; 当一个字符被添加到 SacHook.Input 时调用. { Suffix := "" if RegExMatch(ih.Input, "`nm)\w+$", prefix) && RegExMatch(WordList, "`nmi)^" prefix[0] "\K.*", Suffix) Suffix := Suffix[0] if CaretGetPos(cx, cy) ToolTip Suffix, cx + 15, cy else ToolTip Suffix ; 只在显示工具提示时拦截 Tab 键. ih.KeyOpt("{Tab}", Suffix = "" ? "-NS" : "+NS") } SacKeyDown(ih, vk, sc) { if (vk = 8) ; 退格键 SacChar(ih, "") else if (vk = 9) ; Tab 键 Send "{Text}" Suffix }
等待用户按下任意键. 不产生可见字符的键 -- 比如修饰键, 功能键和箭头键 -- 被列为结束键, 这样它们也会被检测到.
ih := InputHook("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}") ih.Start() ih.Wait()
这是一个可工作的热键示例. 由于热键有波浪(~) 前缀, 它自己的击键将传递到活动窗口. 因此, 如果您在任何编辑器中键入 [btw
(或其他匹配短语之一), 脚本将自动执行您选择的操作(例如替换键入的文本). 有关此示例的另一个版本, 请参阅 Switch.
~[:: { msg := "" ih := InputHook("V T5 L4 C", "{enter}.{esc}{tab}","btw,otoh,fl,ahk,ca") ih.Start() ih.Wait() if (ih.EndReason = "Max") msg := 'You entered "{1}", which is the maximum length of text.' else if (ih.EndReason = "Timeout") msg := 'You entered "{1}" at which time the input timed out.' else if (ih.EndReason = "EndKey") msg := 'You entered "{1}" and terminated the input with {2}.' if msg ; 如果发现了EndReason, 跳过下面的部分. { MsgBox Format(msg, ih.Input, ih.EndKey) return } ; 否则, 找到了匹配. if (ih.Input = "btw") Send("{backspace 4}by the way") else if (ih.Input = "otoh") Send("{backspace 5}on the other hand") else if (ih.Input = "fl") Send("{backspace 3}Florida") else if (ih.Input = "ca") Send("{backspace 3}California") else if (ih.Input = "ahk") Run("https://www.autohotkey.com") }