Jump to content

Wait until any new window appears


micechal
 Share

Go to solution Solved by mikell,

Recommended Posts

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 :)

Link to comment
Share on other sites

  • Moderators

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.

Link to comment
Share on other sites

  • Solution

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
Link to comment
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
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...