Functions:
WinWait and
WinWaitNew
Description
- WinWait is a wrapper for WinWait which supports excluding windows via their Unique ID (HWND)
- WinWait and WinWaitNew work hand-in-hand to allow waiting for a NEW matching window to exist - such as waiting for a new instance of a browser window (see example 2 below).
Download
WinWait.zip
Requirements
None
Functions
WinWait(WinTitle = "", WinText = "", Seconds = "", ExcludeTitle = "", ExcludeText = "")
Wrapper for
WinWait, with support for excluding windows via their Unique ID (HWND). To exclude multiple windows, separate each on a new line.
ReturnValue
Returns the
Unique ID (HWND) of the top-most matching window. This allows the function's return to be used as a quasi-boolean value. The statement WinWait(...) is "true" if a matching window is found, and "false" otherwise.
Note: if ExcludeTitle is a list of IDs, each requires the "ahk_id" - to allow possibly supporting "ahk_pid", "ahk_class", "ahk_group", and multiple window titles.
Because of the form, a
continuation section can be used to create a list of excluded titles.
Ex.
Code:
ExcludeWindows =
(LTrim
ahk_id %WindowID1%
ahk_id %WindowID2%
)
Note: whenever possible, the actual
WinWait command is used. Regardless,
ErrorLevel and the
LastFoundWindow are updated to mimic that of WinWait.
The included function
WinWait_formatIDs(ListOfIDs, delimiter = ","), can be used to format a list of unique IDs for use as an ExcludedTitle.
If ListOfIDs is alphanumeric (and non-numeric), this value is assumed to be the name of an
array. In this case, if
%ListOfIDs%0 is an integer, it is assumed to be the array's size, else
%ListOfIDs% is assumed to be the size. This allows converting a list of window IDs, such as created by
WinGet -> List, to the propper form. Note: this array MUST be in the global scope for the function to work. As a side note, the included
WinWaitNew function wraps
WinGet -> List, and its return can be used as the ExcludedTitle in a call to the WinWait function.
WinWaitNew(WinTitle = "", WinText = "", ExcludeTitle = "", ExcludeText = "")Wrapper for
WinGet -> List. The return is formatted for use as an ExcludeTitle in the WinWait function.
Note: can be used to detect if a new matching window is opened - when used with WinWait (see example 2 below).
Code (for WinWait function)Code:
;a modified WinWait to allow Excluding ahk_ids
;if ExcludeTitle isn't a list of ahks, using the normal WinWait command
WinWait(WinTitle = "", WinText = "", Seconds = "", ExcludeTitle = "", ExcludeText = "")
{
if subStr(ExcludeTitle, 1, 6) = "ahk_id"
{
/*
ExcludeTitle MUST have this form
(this mimics the formatting returned from WinWaitNew
Note: spaces and tabs between "ahk_id" are ignored
Additionally, spaces and tabs after Win# are ignored
ex =
(LTrim
ahk_id Win1
ahk_id Win2
ahk_id Win3
)
*/
;sets ErrorLevel - in accordance with WinWait command
ErrorLevel := 0
if (Seconds = "")
{
Loop
{
if newWindow := WinWait_newWindowExists(WinTitle, WinText, ExcludeTitle, ExcludeText)
{
;updates the Last Found Window - in accordance with WinWait command
WinExist("ahk_id" newWindow)
return newWindow
}
Sleep, 100
}
}
else
{
if (Seconds = 0)
TimeOut := 500
else if Seconds is not number
TimeOut := 500
else
TimeOut := Seconds * 1000
start := A_TickCount
Loop
{
if (A_TickCount - start >= TimeOut)
break
if newWindow := WinWait_newWindowExists(WinTitle, WinText, ExcludeTitle, ExcludeText)
{
;updates the Last Found Window - in accordance with WinWait command
WinExist("ahk_id" newWindow)
return newWindow
}
Sleep, 100
}
;timed out (sets ErrorLevel - in accordance with WinWait command)
ErrorLevel := 1
}
}
else
{
;use the normal WinWait
WinWait, %WinTitle%, %WinText%, %Seconds%, %ExcludeTitle%, %ExcludeText%
if (!ErrorLevel)
{
;match found - returns the window handle
;(allows the functions return to be a quasi-boolean)
WinGet, newWindow, ID
return newWindow
}
}
}
;returns the Unique ID (HWND) for the top-most matching window
WinWait_newWindowExists(WinTitle, WinText, ExcludeTitle, ExcludeText)
{
/*
ExcludeTitle MUST have this form
(this mimics the formatting returned from WinWaitNew
Note: spaces and tabs between "ahk_id" are ignored
Additionally, spaces and tabs after Win# are ignored
ex =
(LTrim
ahk_id Win1
ahk_id Win2
ahk_id Win3
)
*/
;extract the ahk_ids from the ExcludedTitle
excludedIDs := WinWait_extractIDs(ExcludeTitle)
StringSplit, excludedIDs, excludedIDs, `n
;retrieve the list of matching windows
WinGet, newList, List, %WinTitle%, %WinText%, , %ExcludeText%
Loop, %newList%
{
;iterate through the matching windows - top to bottom
TestWindow := newList%A_Index%
listIndex := 0
;loop through the excluded IDs
Loop, %excludedIDs0%
{
if (TestWindow = excludedIDs%A_Index%)
{
listIndex := A_Index
break
}
}
if (listIndex)
{
;the specified window is excluded
continue
}
;the specified window isn't in the excluded IDs - return it
return TestWindow
}
}
;returns a newline-delimited list of the captured number for entries of this form:
;"i)^ahk_id\s*+(Number)$" (leading and trailing spaces and tabs for entries are ignored)
;Number can be either a hex or decimal number
WinWait_extractIDs(ExcludeTitle)
{
/*
ExcludeTitle is a newline-delimited list of "values" (specifically used by WinWait()
*/
Loop, Parse, ExcludeTitle, `n, %A_Space%%A_Tab%
{
if RegExMatch(A_LoopField, "i)^ahk_id\s*+(?<ID>0x[\da-fA-F]++|\d++)$", ahk_)
{
listOfIDs .= ahk_id . "`n"
}
}
;remove the trailing newline character
StringTrimRight, listOfIDs, listOfIDs, 1
return listOfIDs
}
;format the delimited list of Unique IDs (HWNDs) to be used
; as an exclude title in the above WinWait function
WinWait_formatIDs(ListOfIDs, Delimiters = ",")
{
if ListOfIDs is alnum
{
if ListOfIDs is not integer
{
tmp := %ListOfIDs%0
if tmp is integer
size := tmp
else
size := %ListOfIDs%
;format the array to be used by WinWait's ExcludeTitle
Loop, %size%
{
ExcludeTitle .= "ahk_id" . %ListOfIDs%%A_Index% . "`n"
}
;remove the trailing newline character
StringTrimRight, ExcludeTitle, ExcludeTitle, 1
return ExcludeTitle
}
}
;ListOfIDs is a list of Unique ID (HWND) values with the specified delimiter
;omits spaces and tabs surrounding the id
Loop, Parse, ListOfIDs, %Delimiters%, %A_Space%%A_Tab%
{
if A_LoopField is not integer
continue
ExcludeTitle .= "ahk_id" . A_LoopField . "`n"
}
;remove the trailing newline character
StringTrimRight, ExcludeTitle, ExcludeTitle, 1
return ExcludeTitle
}
Code (for WinWaitNew function)Code:
;wrapper for WinGet -> List whose return is
;formatted for use as an ExcludeTitle in the WinWait function
;can be used to detect if a new matching window is opened - when used with WinWait()
WinWaitNew(WinTitle = "", WinText = "", ExcludeTitle = "", ExcludeText = "")
{
WinGet, Window, List, %WinTitle%, %WinText%, %ExcludeTitle%, %ExcludeText%
if (Window = 0)
return
;format them to be used by WinWait's ExcludeTitle
Loop, %Window%
{
ExcludeTitle .= "ahk_id" . Window%A_Index% . "`n"
}
;remove the trailing newline character
StringTrimRight, ExcludeTitle, ExcludeTitle, 1
return ExcludeTitle
}
Example 1Code:
SetTitleMatchMode, RegEx
;Firefox Title RegEx
TitleRegEx := "^(?<Title>.*?) - Mozilla Firefox$"
;uses the WinWait command, since possible
if Window := WinWait(TitleRegEx, "", 0)
{
;a firefox window is opened (the Last Found Window is set to it)
;(Window contains the Unique ID (HWND) for the top-most window)
WinGetTitle, WindowTitle
MsgBox, % "The Unique ID (HWND) for the window: " . Window . "`n"
. "The window title is " . quote(WindowTitle)
}
else
MsgBox, % "Firefox is not open"
;surrounds Text with double quotes - for readability
quote(Text)
{
quote = "
return quote . Text . quote
}
Example 2Code:
;This script activates firefox (must already be open), opens a new window,
;and waits for the new window to exist.
;if FireFox is not already open, the program exists.
SetTitleMatchMode, RegEx
;Firefox Title RegEx
TitleRegEx := "^(?<Title>.*?) - Mozilla Firefox$"
if !WinExist(TitleRegEx)
ExitApp
;returns the list of windows matching the specified criteria (or the empty string, if none)
;(the return is formatted for use in the WinWait function as an ExcludeTitle)
;Note: does not modify the Last Found Window
; ExcludeWindows := WinWaitNew(TitleRegEx)
;equivalent to the above call - demonstrates the function's ability
WinGet, MatchingWindows, List, %TitleRegEx%
ExcludeWindows := WinWait_formatIDs("MatchingWindows")
WinActivate
WinWaitActive
Sleep, 50
Send, ^n
start := A_TickCount
;waits for a new firefox window to open
;(2.5 second timeout)
if NewWindow := WinWait(TitleRegEx, "", 2.5, ExcludeWindows)
{
;a new firefox window was opened (the Last Found Window is set to it)
WinGetTitle, NewWindowTitle
MsgBox, % "The Unique ID (HWND) for the new window: " . NewWindow . "`n"
. "The window title is " . quote(NewWindowTitle)
}
else
MsgBox, % "Timed out: " . (A_TickCount - start)
return
;surrounds Text with double quotes - for readability
quote(Text)
{
quote = "
return quote . Text . quote
}
How to use
Extract the zip's contents to a
library folder for automatic inclusion - StdLib compliant.
A copy of the above examples can be found in the "Func Examples" folder.
Download WinWait function