Sign in to follow this  
Followers 0
micechal

Wait until any new window appears

4 posts in this topic

Hello.

I'm trying to find a way to wait until any new window appears, no matter it's title and contents. Do you know what would be the best way of achieving such behavior?

I tried using

WinWait("")

but that returns also the already open windows, so it isn't of any use.

I thought I could maybe get all the open windows and store them in a table, then in a loop do the same and compare if the tables contain the same data. If not, then some new window has appeared (or was destroyed, whatever :P) but that idea really seems suboptimal to me and I believe there should be a more practical way to do this.

Thank you in advance :)

Share this post


Link to post
Share on other sites



You're not going to be able to get out of a loop (even if calling a built in function, they'll need to loop through their list).

I thought I might have written something like this years and years ago for the forum, but I'll darned if I can find it.

See if this meets your needs (note the array passed is ByRef, the return is the length of the array).

#include <Array.au3>

Global $ga_newWin = 0
Global $gn_uBound = 0
$gn_uBound = _Win_GetNew($ga_newWin)
_ArrayDisplay($ga_newWin)


Run("notepad.exe")
WinWait("Untitled - Notepad")

$gn_uBound = _Win_GetNew($ga_newWin)

; should only show new windows
_ArrayDisplay($ga_newWin)

For $i = 0 To $gn_uBound - 1
    ConsoleWrite("Window Handle: " & $ga_newWin[$i] & _
        " : Window Title: " & WinGetTitle($ga_newWin[$i]) & @CRLF)
Next

Func _Win_GetNew(ByRef $a_oldwin, $v_process = 0, _
        $s_wintitle = Null, $s_wintext = Null, $b_visibleonly = 1)

    ; are we working with a processes windows only?
    If $v_process Then
        $v_process = ProcessExists($v_process)
        If Not $v_process Then Return SetError(1, 0, 0)
    EndIf

    ; provide options for each optional parameter of win/title-text
    Local $a_wlist = 0
    If $s_wintitle Then
        If $s_wintext Then
            $a_wlist = WinList($s_wintitle, $s_wintext)
        Else
            $a_wlist = WinList($s_wintitle)
        EndIf
    ElseIf $s_wintext Then
        $a_wlist = WinList("[REGEXPTITLE:.*?]", $s_wintext)
    Else
        $a_wlist = WinList()
    EndIf

    If Not IsArray($a_wlist) Then
        Return SetError(2, 0, 0)
    EndIf

    Local $h_wnd
    Local $n_next = 0
    Local $a_ret[UBound($a_wlist) - 1]

    For $iwin = 1 To UBound($a_wlist) - 1

        $h_wnd = $a_wlist[$iwin][1]

        If $v_process And Not WinGetProcess($h_wnd) = $v_process Then
            ContinueLoop
        EndIf

        If $b_visibleonly And Not BitAND(WinGetState($h_wnd), 2) Then
            ContinueLoop
        EndIf

        $a_ret[$n_next] = String($h_wnd)
        $n_next += 1
    Next

    ; was anything found
    If Not $n_next Then
        Return SetError(3, 0, 0)
    EndIf

    ReDim $a_ret[$n_next]; resize

    ; if the old array is not an array or is a 2D array then return
    ;  current data already received
    If Not IsArray($a_oldwin) Or UBound($a_oldwin, 2) Then
        $a_oldwin = $a_ret
        Return UBound($a_ret)
    EndIf

    ; scripting dictionary does not like the handles
    For $i = 0 To $n_next - 1
        $a_ret[$i] = String($a_ret[$i])
    Next

    ; mikell shared this option I've not seen before:
    ;  http://www.autoitscript.com/forum/topic/165667-delete-matches-on-2-file-lists/#entry1209704
    Local $o_sd1 = ObjCreate("Scripting.Dictionary")
    Local $o_sd2 = ObjCreate("Scripting.Dictionary")
    For $i In $a_oldwin
        $o_sd1.Item($i)
    Next
    For $i In $a_ret
        $o_sd2.Item($i)
    Next
    For $i In $o_sd2
        If $o_sd1.Exists($i) Then
            $o_sd2.Remove($i)
        EndIf
    Next
    $a_ret = $o_sd2.Keys();

    Local $l_retsize = UBound($a_ret)

    If Not $l_retsize Then
        Return SetError(4, 0, 0)
    EndIf

    ; convert back to window handles
    For $i = 0 To $l_retsize - 1
        $a_ret[$i] = HWnd($a_ret[$i])
    Next

    $a_oldwin = $a_ret
    Return $l_retsize
EndFunc

Common sense plays a role in the basics of understanding AutoIt... If you're lacking in that, do us all a favor, and step away from the computer.

Share this post


Link to post
Share on other sites

Hmm you're right, my code was not accurate enough, it should check visible windows only and not fire on a window close

This one should be better

#include <MsgBoxConstants.au3>

Global $n0 = _GetWnd()
; MsgBox($MB_TOPMOST,"", $n0)
Do
    $n1 = _GetWnd()
Until $n1 > $n0
MsgBox($MB_TOPMOST,"", "boo")


Func _GetWnd()
  Local $list = WinList("[REGEXPTITLE:\S+]")
  Local $nb = $list[0][0]
  For $i = 1 To $list[0][0]
    If Not BitAND(WinGetState($list[$i][1]), 2) Then $nb -= 1
  Next
  If $nb < $n0 Then $n0 = $nb
  Return $nb
EndFunc

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!


Register a new account

Sign in

Already have an account? Sign in here.


Sign In Now
Sign in to follow this  
Followers 0