以创建的相反顺序关闭 windows

Close windows in reverse order of creation

我有一个主程序 window 和多个其他 windows,我想使用 autoit 关闭这些 windows。然而,如果程序的其他 windows 打开并创建一条警告消息,主 window 将拒绝关闭。

为了避免这种情况,我想先关闭另一个 windows。

由于程序的编写方式,windows不是父子关系,所以我不能在"user32.dll"中使用"EnumChildWindows"。

所以我的另一个选择是获取 windows 的创建顺序或时间,然后以相反的顺序关闭它们。有什么办法吗?

您可以尝试通过流程获取。据我所知,下面的函数将 return windows 的 z 顺序,而无需您从自己的代码中跟踪 windows 本身的 "creation time",你不会得到可以做到这一点的解决方案。

#include <WinAPIProc.au3>
#include <WinAPISys.au3>

#region - Example
Global $gahWnd[3]
For $i = 0 To 2
    $gahWnd[$i] = GUICreate("Example " & $i)
    GUISetState(@SW_SHOW, $gahWnd[$i])
Next


Global $gaExample = _WinGetByProc(@AutoItPID)
If @error Then Exit 2
Sleep(3000) ; so you can at least see the windows were created

; windows are returned in the "last z-order"
;  so they'll be returned "Example 2, Example 1, Example 0"
;  This makes it easy to close all but the first one

; use -1 to keep the first window created
For $i = 1 To $gaExample[0] - 1
    ConsoleWrite("Closing: " & $gaExample[$i] & ":" & WinGetTitle($gaExample[$i]) & @CRLF)
    WinClose($gaExample[$i])
Next

Global $gaMsg
While 1
    $gaMsg = GUIGetMsg(1)
    Switch $gaMsg[1]
        Case $gahWnd[0]
            Switch $gaMsg[0]
                Case -3
                    Exit
            EndSwitch
        Case $gahWnd[1]
            Switch $gaMsg[0]
                Case -3
                    GUIDelete($gahWnd[1])
            EndSwitch
        Case $gahWnd[2]
            Switch $gaMsg[0]
                Case -3
                    GUIDelete($gahWnd[2])
            EndSwitch
    EndSwitch
WEnd
#EndRegion - Example

; pass the exe or the process id
Func _WinGetByProc($vExe)

    ; will return pid if exe name sent or validate if pid is sent
    Local $iPID = ProcessExists($vExe)
    If Not ProcessExists($iPID) Then
        Return SetError(1, 0, 0)
    EndIf

    ; enum desktop window only (top-level-windows)
    Local $ahWnds = _WinAPI_EnumDesktopWindows(_WinAPI_GetThreadDesktop( _
                _WinAPI_GetCurrentThreadId()))
    If @error Or Not IsArray($ahWnds) Then
        Return SetError(2, 0, 0)
    EndIf

    Local $aExeContainer[11], $iDim
    For $iwnd = 1 To $ahWnds[0][0]
        ; compare windows pid with our pid
        If (WinGetProcess(HWnd($ahWnds[$iwnd][0])) = $iPID) Then
            $iDim += 1
            ; sanity check, be sure the array has the right number of indexes
            If (Mod($iDim, 10) = 0) Then
                ReDim $aExeContainer[$iDim + 10]
            EndIf
            $aExeContainer[$iDim] = HWnd($ahWnds[$iwnd][0])
        EndIf
    Next

    ; if there were no matches return
    If Not $iDim Then
        Return SetError(3, 0, 0)
    EndIf

    ; trim array and set number found in the zero index
    ReDim $aExeContainer[$iDim + 1]
    $aExeContainer[0] = $iDim

    Return $aExeContainer
EndFunc