问题
我希望 AutoHotkey 自动检测某个弹出对话框的出现时间并采取某些操作。我该怎么做?
具体例子
在我的特定情况下,我希望 AutoHotkey 关闭更新目录当我想更新目录时 Word 会显示对话框。
工作流程如下:
我更新了 Word 文档中的标题
我按Ctrl+A选择整个文档
我按下F9以更新所有字段
现在,我需要按下来Arrow down选择更新整个表然后Enter按好的并继续
我希望 AutoHotkey 自动发出Arrow down,Enter命令,因为上述工作流程是我每天执行十几次的。
当然,因为我启动了工作流程,所以我可以编写一个 AutoHotkey 脚本,以Ctrl+开头为我完成整个操作A,如下所示:
#IfWinActive ahk_class OpusApp
F9::
Send, ^a
Send, {F9}
Sleep, 200
Send, {Down}
Send, {Enter}
return
但是,上面的例子只是为了说明目的,有些情况下弹出对话框是随机出现的,我希望 AutoHotkey 根据弹出对话框的标题执行一些操作。
我迄今为止的研究
- 一些互联网资源建议使用 AutoHotkey 循环它会无限循环并检查(比如说每秒一次)是否存在具有特定标题的窗口,然后将其关闭。但我发现这很浪费 CPU 资源
- 其他一些互联网资源提到壳钩以及一个代码片段,我认为这是可行的方法,但我不明白该代码片段;有人可以解释它是如何工作的,并给出一个可以理解的例子,如果这是解决方案吗?
以下代码片段是从这里复制。
SetBatchLines, -1
Process, Priority,, High
Gui +LastFound
hWnd := WinExist()
DllCall( "RegisterShellHookWindow", UInt,hWnd )
MsgNum := DllCall( "RegisterWindowMessage", Str,"SHELLHOOK" )
OnMessage( MsgNum, "ShellMessage" )
Return
ShellMessage( wParam,lParam ) {
If ( wParam = 32772 or WParam = 4) ; HSHELL_WINDOWACTIVATED := 4 or 32772
WinGetActiveTitle, Title
If ( Title = "sun 4 - foxtrot - Remote Desktop Connection" )
SetCapsLockState, on
else SetCapsLockState, off
}
我看到了
If (Title = "sun 4 - foxtrot - Remote Desktop Connection")
部分。其余部分做什么?
答案1
你说得太深奥了。为给定的窗口名称设置一个程序监视器不会对系统资源造成太大负担。这可能是可行的方法。
ShellMessage
可以是您选择的任何名称,因为它是 调用的函数OnMessage
,当您的脚本收到消息时会触发该函数。此函数的内容应该是您的代码,以确保您在正确的窗口中,然后发出要发送的命令。您的函数最多可以接受四个参数,按照帮助文件中的定义为了OnMessage
。
这些DllCall
行是与 Windows 绑定以从系统获取消息的神秘部分。如果您要与 Windows 绑定,您应该在这里知道自己在做什么。
SetBatchLines, -1
并Process, Priority,, High
说您的脚本非常重要,应该始终全速运行,并且任何其他系统进程都不应减慢它的速度。
Gui +LastFound
并hWnd := WinExist()
找到此脚本运行时的唯一 ID,以便可以在后续的 Windows 中注册它DllCall
。
答案2
为了获得不轮询且响应更快的高效代码,您可以在此处调整代码:
在文件的设置部分添加以下语句:
Update Table of Contents ahk_exe WINWORD.EXE B WordTOCupdate
Update Table of Figures ahk_exe WINWORD.EXE B WordTOCupdate
确保脚本的此设置部分的列之间有制表符(而不是空格,具体取决于您使用的编辑器)。exe 名称也区分大小写,因为它使用 RegEx 匹配,除非您更改它。
然后此代码在脚本主体中运行......
;-------------------------------------------------------
; Check for Microsoft Word Update Table of Contents
;-------------------------------------------------------
WordTOCupdate:
WinActivate ;Set Window to Be on top
SendInput !e{Enter}
return
您也可以使用您发布的代码片段...它基本上是同一件事。
Gui +LastFound
hWnd := WinExist()
DllCall( "RegisterShellHookWindow", UInt,hWnd )
MsgNum := DllCall( "RegisterWindowMessage", Str,"SHELLHOOK" )
OnMessage( MsgNum, "ShellMessage" )
Return
ShellMessage( wParam,lParam ) {
If ( wParam = 32772 or WParam = 4) ; HSHELL_WINDOWACTIVATED := 4 or 32772
WinGetActiveTitle, Title
If (Title="Update Table of Contents" )
{
SendInput !e{Enter}
}
}
!e 发送 Alt+e 来更新整个表。