如何在 AutoHotkey 中等待两个或多个不同的窗口
Posted
技术标签:
【中文标题】如何在 AutoHotkey 中等待两个或多个不同的窗口【英文标题】:How to winwait for two or more different windows in AutoHotkey 【发布时间】:2022-01-12 10:19:59 【问题描述】:是否可以同时WinWaitActive
为两个(或更多)不同的窗口标题?我正在执行一个命令,可能会出现一个成功的 VNC 窗口或一个对话框告诉我连接失败。
run, vnc.cmd, , Hide , PID ;# Launch hidden
WinWait, TurboVNC info, ;# The Warning
MsgBox A
WinWait, VNC manager [Raw] - 99`%,
MsgBox B
因此,如果 VNC 正确显示,这个最小示例显然不起作用,因为永远不会按顺序到达 B
。所以它试图用计时器来解决这个问题,我认为它们有单独的线程:
run, vnc.cmd, , Hide , PID ;# Launch hidden
SetTimer, wait_for_graphical_vnc_own_thread, -1 ;# previously I had a 0 here, but that was not the problem's source
WinWait, TurboVNC info, ;# The Warning
MsgBox A
wait_for_graphical_vnc_own_thread:
WinWait, VNC manager [Raw] - 99`%, ;# Successful window
MsgBox B
不幸的是,这也不起作用,即使使用另一个(第二个)计时器来发出警告也是如此。接下来我尝试的是取自this deprecated board:
Gui +LastFound
hWnd := WinExist()
DllCall( "RegisterShellHookWindow", UInt, hWnd )
MsgNum := DllCall( "RegisterWindowMessage", Str,"SHELLHOOK" )
OnMessage( MsgNum, "ShellMessage" )
Return ; // End of Auto-Execute Section //
ShellMessage( wParam,lParam )
If ( wParam = 4 ) ; HSHELL_WINDOWACTIVATED
WinGetTitle, Title, ahk_id %lParam%
MsgBox %Title% ;# Not even this is ever shown
If InStr( Title, "TurboVNC info" )
MsgBox A2
If InStr( Title, "VNC manager [Raw] - 99`%" )
MsgBox B2
虽然我喜欢这个想法,但两者都没有推出。作者指向this board question on how to Hook on to Shell to receive its messages (archive link)了解更多详情。最后一个想法来自this answer to a question about AutoIt:
SetTitleMatchMode, RegEx
WinWait, TurboVNC info|VNC manager [Raw] - 99`%,
MsgBox C
;# I would then have a condition here to separate the two cases, but not even C gets shown
【问题讨论】:
【参考方案1】:在普通 AHK 中,这确实不像只运行两个 WinWaitActive
命令那么容易,因为普通 AHK 不是多线程的。您可以在 AHK_H 中执行此操作,但那完全是另一回事。
在正常的 AHK 中,您找到的 shell 挂钩实现工作正常。
您只需要考虑HSHELL_RUDEAPPACTIVATED
消息。这是大多数时间实际发送的消息(我不知道为什么,它只是大声笑)。
#NoEnv
DllCall("RegisterShellHookWindow", Ptr, A_ScriptHwnd)
MsgNum := DllCall("RegisterWindowMessage", Str, "SHELLHOOK")
OnMessage(MsgNum, "ShellMessage")
Return
ShellMessage(wParam, lParam)
static HSHELL_WINDOWACTIVATED := 0x04
, HSHELL_HIGHBIT := 0x8000
, HSHELL_RUDEAPPACTIVATED := HSHELL_WINDOWACTIVATED | HSHELL_HIGHBIT
if (wParam == HSHELL_RUDEAPPACTIVATED || wParam == HSHELL_WINDOWACTIVATED)
WinGetTitle, title, % "ahk_id " lParam
ToolTip, % (wParam == HSHELL_WINDOWACTIVATED ? "HSHELL_WINDOWACTIVATED" : "HSHELL_RUDEAPPACTIVATED") " message received!`nWindow activated: " title "`nHWND: " lParam
另外,作为旁注,你的这行语法不正确If InStr( Title, "VNC manager [Raw] - 99`%" )
.
你只需要在遗留语法中转义这些东西。在这里,您使用了一个函数,这意味着您使用的是现代表达式语法,并且您在 " "
中明确指定了一个字符串。并且%
字符在字符串中没有任何特殊含义,所以那里没有什么可以转义的。
所以,长话短说,删除`
。
RegEx 方法也可以,但 VNC manager [Raw] - 99%
不是您想要的 RegEx。[ ]
在 RegEx 中具有特殊含义 (它是 character class) ,所以你需要转义这些字符。
SetTitleMatchMode, RegEx
WinWaitActive, % "TurboVNC info|VNC manager \[Raw\] - 99%"
WinGetTitle, title, A
ToolTip, % title " activated!"
【讨论】:
【参考方案2】:我找到了解决方法。调用:
run, vnc_close_helper.ahk, PID_ch
实际上在单独的线程中运行。然后帮助脚本包含我需要的第二个WinWaitActive
。
【讨论】:
以上是关于如何在 AutoHotkey 中等待两个或多个不同的窗口的主要内容,如果未能解决你的问题,请参考以下文章
当两个或多个进程(应用程序)等待将数据放入同一个缓冲区时,是不是保证顺序?