使用 AutoHotKey 防止物理按键与发送的键冲突

Preventing physical key presses from conflicting with sent keys using AutoHotKey

我想使用 autohotkey 定义一个快捷方式,自动导航到 Word 功能区菜单中的单元格宽度文本框(即发送键 Alt,j,l,w while in Word).

我对脚本的最初尝试引入了一个问题,即在脚本发送键之前,物理按键的 Up 操作尚未完成,导致脚本失败。

虽然我有一个解决方法(使用 sleep 250,如下所示),但我想了解是否有更优雅的解决方案 - 例如此值是通过反复试验选择的,此解决方法可能在另一台机器上失败,或者如果我的笔记本电脑今天运行不佳。

基本上,我想找到一个解决方案,避免对等待时间进行硬编码。

有什么建议吗?


问题

在我的初始脚本中,我尝试定义热键 Alt+Shift+p在 Word 中,发送 Altjlw 按顺序。这失败了,而是将文本 "jlw" 输入到活动的 table 单元格中。

这是因为对于物理按下的键(在下面的评论中用 # 标记),Up 操作尚未 运行 当脚本已经开始发送键时(指示$)。这会打乱发送顺序 Alt,j,l,w 所以它失败了。

另请注意,标有 ? 的事件可能是失败操作的副产品。

脚本

; Jump to table cell width entry when Alt+Shift+p pressed in Word only
#IfWinActive, ahk_exe WINWORD.EXE
!+p::
Send, {RAlt down}{RAlt up}jlw
Return

密钥历史记录

VK  SC  Type    Up/Dn   Elapsed Key     Comment
-------------------------------------------------------------------------------------------------------------
A4  038     d   1.03    LAlt            #
A0  02A     d   0.14    LShift          #
50  019 h   d   0.13    p               #, h=Hook Hotkey
A5  138 i   d   0.02    RAlt            $
A5  138 i   u   0.00    RAlt            $
11  01D i   d   0.00    Control         ?
11  01D i   u   0.00    Control         ?
A4  038 i   u   0.00    LAlt            #
A0  02A i   u   0.00    LShift          #
4A  024 i   d   0.00    j               $
4A  024 i   u   0.00    j               $
4C  026 i   d   0.00    l               $
4C  026 i   u   0.00    l               $
57  011 i   d   0.00    w               $
57  011 i   u   0.00    w               $
11  01D i   d   0.00    Control         ?
A4  038 i   d   0.00    LAlt            ?
11  01D i   u   0.00    Control         ?
A0  02A i   d   0.00    LShift          ?
50  019 s   u   0.08    p               #
A0  02A     u   0.25    LShift          ?
A4  038     u   0.00    LAlt            ?

解决方法

通过添加 sleep 250 语句,热键和发送键按预期顺序 运行。请注意,没有其他键被触发(? 没有指示)。

脚本

; Jump to table cell width entry when Alt+Shift+p pressed in Word only
#IfWinActive, ahk_exe WINWORD.EXE
!+p::
Sleep 250
Send, {RAlt down}{RAlt up}jlw
Return

密钥历史记录

VK  SC  Type    Up/Dn   Elapsed Key     Comment
-------------------------------------------------------------------------------------------------------------
A4  038     d   0.39    LAlt            #
A0  02A     d   0.20    LShift          #
50  019 h   d   0.20    p               #, h=Hook Hotkey
50  019 s   u   0.11    p               #
A0  02A     u   0.11    LShift          #
A4  038     u   0.00    LAlt            #
A5  138 i   d   0.03    RAlt            $
A5  138 i   u   0.00    RAlt            $
4A  024 i   d   0.00    j               $
4A  024 i   u   0.00    j               $
4C  026 i   d   0.00    l               $
4C  026 i   u   0.00    l               $
57  011 i   d   0.00    w               $
57  011 i   u   0.00    w               $, SUCCESS!

如果目标window没有可靠地接收到击键,您可以尝试通过SetKeyDelay的第二个参数在发送命令中增加按键持续时间,例如

!+p::
    SetKeyDelay, 10, 10
    Send, {RAlt down}{RAlt up}jlw
Return

不确定您为什么使用正确的 alt,甚至认为这不应该起作用。只需使用 "Alt"。而且我认为您的热键对此不是很好。 Word 与输入混淆。
但我认为也许这样做会奏效

!+p up:: ;up means it'll run once u release p, might help a bit
    SetKeyDelay, 500, 10 ;good amount of delay, can probably do with less
    Send, {Shift Up}{Alt Up}{Alt}jlw ;send shift and alt up first
Return

现在有一个更好的选择,用 Word ComObject. Usage of VBA 自动化它,因为这是 正常 和预期的方式,但你可以 AHK(或任何其他语言) 也一样。
这是更改第一个 table 的第一个单元格宽度的快速 AHK 示例:

Word := ComObjActive("Word.Application")
Word.ActiveDocument.Tables(1).Cell(1, 1).Width := 500

当然,这不是解决此问题的好方法,我相信您可以以某种方式引用活动 table 和活动单元格,我只是快速阅读文档并写下了它。我自己实际上从来没有在实践中使用过这些东西。

我使用 KeyWait 找到了一个更优雅的解决方案。与我之前的解决方法脚本相比,我认为这更优雅,因为它不需要硬编码等待时间。这只是在脚本继续之前等待按下的键出现,防止任何冲突:

脚本

#IfWinActive, ahk_exe WINWORD.EXE
!+p::
KeyWait Alt
KeyWait Shift
KeyWait p
Send, {Alt Down}{Alt Up}jlw
Return

密钥历史记录

VK  SC  Type    Up/Dn   Elapsed Key     Comment using previous notation
-------------------------------------------------------------------------------------------------------------
A4  038     d   0.63    LAlt            #
A0  02A     d   0.11    LShift          #
50  019 h   d   0.11    p               #
50  019 s   u   0.06    p               #
A0  02A     u   0.19    LShift          #
A4  038     u   0.00    LAlt            #
12  038 i   d   0.01    Alt             $
12  038 i   u   0.00    Alt             $
4A  024 i   d   0.00    j               $
4A  024 i   u   0.00    j               $
4C  026 i   d   0.00    l               $
4C  026 i   u   0.00    l               $
57  011 i   d   0.00    w               $
57  011 i   u   0.00    w               $

有趣的是,修改为使用 Send, !jlw 的上述脚本有效(即导航到“单元格宽度”框),但发送的键按如下顺序出现。我不会使用它,只是为了避免这种乱序发生的任何意外后果。

VK  SC  Type    Up/Dn   Elapsed Key     Comment 
-------------------------------------------------------------------------------------------------------------
A4  038     d   1.17    LAlt            
A0  02A     d   0.11    LShift          
50  019 h   d   0.14    p               
50  019 s   u   0.09    p               
A0  02A     u   0.16    LShift          
A4  038     u   0.00    LAlt            
A4  038 i   d   0.02    LAlt            <--
4A  024 i   d   0.00    j               
4A  024 i   u   0.00    j               
A4  038 i   u   0.00    LAlt            <--
4C  026 i   d   0.00    l               
4C  026 i   u   0.00    l               
57  011 i   d   0.00    w               
57  011 i   u   0.00    w