如何在 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 中等待两个或多个不同的窗口的主要内容,如果未能解决你的问题,请参考以下文章

当两个或多个进程(应用程序)等待将数据放入同一个缓冲区时,是不是保证顺序?

MySQL面试题之死锁

如何在单个 C# 函数中为两个或多个不同的变量使用相同的名称? [关闭]

Autohotkey如何编写框选多行文本或表格的动作?

死锁面试题

如何合并两个或多个具有不同 where 条件的查询?我必须重用在第一个代码中使用的代码