AutoHotkey Community

It is currently May 27th, 2012, 1:29 pm

All times are UTC [ DST ]




Post new topic Reply to topic  [ 1 post ] 
Author Message
PostPosted: March 27th, 2009, 12:25 am 
Offline

Joined: November 4th, 2008, 9:23 am
Posts: 1045
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 1
Code:
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 2
Code:
;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

_________________
As always, if you have any further questions, don't hesitate to ask.

Add OOP to your scripts via the Class Library. Check out my scripts.


Report this post
Top
 Profile  
Reply with quote  
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 1 post ] 

All times are UTC [ DST ]


Who is online

Users browsing this forum: Bon, Yahoo [Bot] and 14 guests


You can post new topics in this forum
You can reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Powered by phpBB® Forum Software © phpBB Group