Reputation: 1676
Is it possible to WinWaitActive
for two (or more) different window titles at the same time? I'm executing a command and there could be a successful VNC Window coming up or a dialog telling me that the connection failed.
run, vnc.cmd, , Hide , PID ;# Launch hidden
WinWait, TurboVNC info, ;# The Warning
MsgBox A
WinWait, VNC manager [Raw] - 99`%,
MsgBox B
So this minimal example obviously doesn't work if the VNC shows correctly, as B
is never reached sequentially. So it was tried to combat this with timers, I thought they had separate threads:
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
Unfortunately, this does also not work, not even with another (second) timer for the warning. The next thing I tried was taken from 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
}
}
While I like the idea, it launches neither of the two. The author points to this board question on how to Hook on to Shell to receive its messages (archive link) for more details. The last idea comes from 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
Upvotes: 0
Views: 2748
Reputation: 101
Tried this and it worked properly:
#Persistent
Gui +LastFound
hWnd := WinExist()
DetectHiddenWindows, On
DllCall( "RegisterShellHookWindow", UInt,hWnd )
MsgNum := DllCall( "RegisterWindowMessage", Str,"SHELLHOOK" )
OnMessage( MsgNum, "ShellMessage" )
Return
ShellMessage( wParam,lParam )
{
If ( wParam = 1 ) ; <-- correct wParam value
{
WinGetTitle, title, ahk_id %lParam%
MsgBox, title = %title% ; this shows properly now
if InStr(title, "calc")
MsgBox, This is Calculator
if InStr(title, "notepad")
MsgBox, This is Notepad
}
}
Upvotes: 0
Reputation: 21
Set SetTitleMatchMode
to RegEx
[v1.0.45+] changes WinTitle
, WinText
, ExcludeTitle
, and ExcludeText
to accept regular expressions.
SetTitleMatchMode RegEx
WinWaitActive, "TurboVNC info|VNC manager \[Raw\] - 99%", , 3 ; waiting one of two windows
if ErrorLevel ;
{
MsgBox Non one of windows appeared
return
}
Upvotes: 1
Reputation: 331
Another solution for some one that doesn't feel they are up to learning regex:
#Persistent
; hotkey or other stuff...
currentWin := winWaitActives("ahk_id " . winActive("A"), 10
, "some win title"
, "some other wintitle"
, " and yet another win title")
Return ; end auto-execute section
; FUNCTION DEFINTION BELOW
winWaitActives(waitNotActiveTitle, waitSeconds, winWaitTitles*) { ; THE ASTERISK PROVIDES A VARIABLE NUMBER OF PARAMS TO THE FUNCTION
; THIS FIRST COMMAND GIVES A POSITIVE POINT TO START THE LOOP.
winWaitNotActive, %waitNotActiveTitle%,, %waitSeconds%
; START LOOPING THROUGH THE TITLES UNTIL FOUND.
for i, winTitle in winWaitTitles {
if (winActive(winTitle)) {
winGetActiveTitle, fullTitle
Break
}
}
Return fullTitle
}
Upvotes: 2
Reputation: 1676
I found a workaround. Calling:
run, vnc_close_helper.ahk, PID_ch
Actually runs in a separate thread. The helper script then contains the second WinWaitActive
I need.
Upvotes: 0
Reputation: 6499
In normal AHK this is indeed not as easy as just running two WinWaitActive
commands, because normal AHK is not multi threaded. You could do this in AHK_H, but that's a whole another thing.
In normal AHK, the shell hook implementation you found, works just fine.
You just need to account for the HSHELL_RUDEAPPACTIVATED
message. This is the message that actually gets sent most of the time (I don't know why, it just is lol).
#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
}
}
Also, as a side note, this line of yours has incorrect syntax
If InStr( Title, "VNC manager [Raw] - 99`%" )
.
You only need to escape such things in legacy syntax. Here you're using a function, which means you're in the modern expression syntax and you're explicitly specifying a string in " "
. And the %
character doesn't have any special meaning in a string, so there's nothing to escape there.
So, long story short, remove `
.
Also that RegEx approach would've worked, but this VNC manager [Raw] - 99%
is not the RegEx you'd want.
[ ]
has special meaning in RegEx (it's a character class), so you need to escape those characters.
SetTitleMatchMode, RegEx
WinWaitActive, % "TurboVNC info|VNC manager \[Raw\] - 99%"
WinGetTitle, title, A
ToolTip, % title " activated!"
Upvotes: 2