OnEventMode - GUI anhalten bis GUI geschlossen wird

  • Grüßt euch erstmal,

    ich hab hier ein Skript was erstmal nichts spannendes macht außer 2 GUIs anzuzeigen. Jetzt habe ich das Problem, dass wenn ich in Zeile 51 ankomme, er sofort nachdem er mit gui2() durch ist, die nachfolgenden Befehle abarbeitet, also hier die MessageBox. Mal angenommen ich möchte mein gui2() solange pausieren, bis es geschlossen wird, aber trotzdem die Möglichkeit haben, meine registrierten Funktionen in gui2 zu benutzen und das danach (nachdem gui2 geschlossen wurde) erst die MessageBox und nachfolgende Befehle ausgeführt werden. Wie könnte man das realisieren?

    [autoit]

    #include <GUIConstantsEx.au3>

    [/autoit][autoit][/autoit][autoit]

    Opt("GUIOnEventMode", 1)

    [/autoit][autoit][/autoit][autoit]

    Global $hGUI1, $hGUI2 = 9999, $hButton1, $hButton2, $hButton3 = 9999 ; Predeclare the variables with dummy values to prevent firing the Case statements

    [/autoit][autoit][/autoit][autoit]

    gui1()

    [/autoit][autoit][/autoit][autoit]

    Func gui1()
    $hGUI1 = GUICreate("Gui 1", 200, 200, 100, 100)
    GUISetOnEvent($GUI_EVENT_CLOSE, "On_Close") ; Call a common GUI close function
    $hButton1 = GUICtrlCreateButton("Msgbox 1", 10, 10, 80, 30)
    GUICtrlSetOnEvent(-1, "On_Button") ; Call a common button function
    $hButton2 = GUICtrlCreateButton("Show Gui 2", 10, 60, 80, 30)
    GUICtrlSetOnEvent(-1, "On_Button") ; Call a common button function
    GUISetState()

    [/autoit][autoit][/autoit][autoit]

    While 1
    Sleep(10)
    WEnd
    EndFunc ;==>gui1

    [/autoit][autoit][/autoit][autoit]

    Func gui2()
    $hGUI2 = GUICreate("Gui 2", 200, 200, 350, 350, -1, -1, $hGUI1)
    GUISetOnEvent($GUI_EVENT_CLOSE, "On_Close") ; Call a common GUI close function
    $hButton3 = GUICtrlCreateButton("MsgBox 2", 10, 10, 80, 30)
    GUICtrlSetOnEvent(-1, "On_Button") ; Call a common button function
    GUISetState()

    [/autoit][autoit][/autoit][autoit]

    ;~ While 1
    ;~ Sleep(10)
    ;~ WEnd
    EndFunc ;==>gui2

    [/autoit][autoit][/autoit][autoit]

    Func On_Close()
    Switch @GUI_WINHANDLE ; See which GUI sent the CLOSE message
    Case $hGUI1
    Exit ; If it was this GUI - we exit <<<<<<<<<<<<<<<
    Case $hGUI2
    GUIDelete($hGUI2) ; If it was this GUI - we just delete the GUI <<<<<<<<<<<<<<<
    GUICtrlSetState($hButton2, $GUI_ENABLE)
    EndSwitch
    EndFunc

    [/autoit][autoit][/autoit][autoit]

    Func On_Button()
    Switch @GUI_CTRLID ; See which button sent the message
    Case $hButton1
    MessageBox(1) ; We can call a function with parameters here <<<<<<<<<<<<<<<<<<<
    Case $hButton2
    GUICtrlSetState($hButton2, $GUI_DISABLE)
    gui2()
    ; hier pausieren, bis gui2() geschlossen wurde, aber es muss möglich sein die registrierten Funktionen in gui2 zu benutzen
    ;~ While 1
    ;~ Sleep(10)
    ;~ WEnd
    MsgBox(0, "sfdsf", "sdfsfd") ; hier weiter machen, nachdem gui2 nicht mehr benötigt wird (geschlossen wurde)
    Case $hButton3
    MessageBox(2) ; We can call a function with parameters here <<<<<<<<<<<<<<<<<<<
    EndSwitch
    EndFunc

    [/autoit][autoit][/autoit][autoit]

    Func MessageBox($iIndex)
    MsgBox("", "MsgBox " & $iIndex, "Test from Gui " & $iIndex)
    EndFunc

    [/autoit]
  • Grundlegend kannst du das Skript bzw. die Funktion in Bezug auf ein Fenster mit WinWaitClose() bzw. WinWait() anhalten, je nachdem ob du darauf wartest das es geschlossen bzw. geöffnet wird.
    Während es wartet ist es jedoch nicht mehr ansprechbar.

    Damit die UIs weiterhin funktionieren, musst du die betreffende Funktion z.B. mit AdlibRegister() aufrufen (und mit AdlibUnRegister() am Ende schließen), sodass der Rest des Skriptes weiterhin ausgeführt werden kann:

    Spoiler anzeigen
    [autoit]

    #include <GUIConstantsEx.au3>

    [/autoit] [autoit][/autoit] [autoit]

    Opt("GUIOnEventMode", 1)

    [/autoit] [autoit][/autoit] [autoit]

    Global $hGUI1, $hGUI2 = 9999, $hButton1, $hButton2, $hButton3 = 9999 ; Predeclare the variables with dummy values to prevent firing the Case statements

    [/autoit] [autoit][/autoit] [autoit]

    gui1()

    [/autoit] [autoit][/autoit] [autoit]

    Func gui1()
    $hGUI1 = GUICreate("Gui 1", 200, 200, 100, 100)
    GUISetOnEvent($GUI_EVENT_CLOSE, "On_Close") ; Call a common GUI close function
    $hButton1 = GUICtrlCreateButton("Msgbox 1", 10, 10, 80, 30)
    GUICtrlSetOnEvent(-1, "On_Button") ; Call a common button function
    $hButton2 = GUICtrlCreateButton("Show Gui 2", 10, 60, 80, 30)
    GUICtrlSetOnEvent(-1, "On_Button") ; Call a common button function
    GUISetState()

    [/autoit] [autoit][/autoit] [autoit]

    While 1
    Sleep(10)
    WEnd
    EndFunc ;==>gui1

    [/autoit] [autoit][/autoit] [autoit]

    Func gui2()
    $hGUI2 = GUICreate("Gui 2", 200, 200, 350, 350, -1, -1, $hGUI1)
    GUISetOnEvent($GUI_EVENT_CLOSE, "On_Close") ; Call a common GUI close function
    $hButton3 = GUICtrlCreateButton("MsgBox 2", 10, 10, 80, 30)
    GUICtrlSetOnEvent(-1, "On_Button") ; Call a common button function
    GUISetState()

    [/autoit] [autoit][/autoit] [autoit]

    ;~ While 1
    ;~ Sleep(10)
    ;~ WEnd
    EndFunc ;==>gui2

    [/autoit] [autoit][/autoit] [autoit]

    Func On_Close()
    Switch @GUI_WINHANDLE ; See which GUI sent the CLOSE message
    Case $hGUI1
    Exit ; If it was this GUI - we exit <<<<<<<<<<<<<<<
    Case $hGUI2
    GUIDelete($hGUI2) ; If it was this GUI - we just delete the GUI <<<<<<<<<<<<<<<
    GUICtrlSetState($hButton2, $GUI_ENABLE)
    EndSwitch
    EndFunc

    [/autoit] [autoit][/autoit] [autoit]

    Func ShowGUI2()
    GUICtrlSetState($hButton2, $GUI_DISABLE)
    gui2()
    WinWaitClose("Gui 2", "")

    [/autoit] [autoit][/autoit] [autoit]

    MsgBox(0, "sfdsf", "sdfsfd") ; hier weiter machen, nachdem gui2 nicht mehr benötigt wird (geschlossen wurde)
    AdlibUnRegister("ShowGUI2")
    EndFunc

    [/autoit] [autoit][/autoit] [autoit]

    Func On_Button()
    Switch @GUI_CTRLID ; See which button sent the message
    Case $hButton1
    MessageBox(1) ; We can call a function with parameters here <<<<<<<<<<<<<<<<<<<
    Case $hButton2
    AdlibRegister("ShowGUI2")

    [/autoit] [autoit][/autoit] [autoit]

    Case $hButton3
    MessageBox(2) ; We can call a function with parameters here <<<<<<<<<<<<<<<<<<<
    EndSwitch
    EndFunc

    [/autoit] [autoit][/autoit] [autoit]

    Func MessageBox($iIndex)
    MsgBox("", "MsgBox " & $iIndex, "Test from Gui " & $iIndex)
    EndFunc

    [/autoit]

    Aber gibt es einen Grund, weshalb du die GUIs in separaten Funktionen erstellst?
    Ich pers. erstelle mit OnEvent alle GUIs zu Beginn und blende diese dann bei Bedarf ein/aus (GuiSetState()); so hast du auch nur deine normale While-Schleife für das Skript, außerhalb einer Funktion.

    Bei einem simplen Skript macht dies zumindest keinen Unterschied in Bezug auf die Ressourcen und ist auf Dauer simpler zu managen.

    3 Mal editiert, zuletzt von Matricus (30. Oktober 2014 um 06:36)

    • Offizieller Beitrag

    Grundlegend kannst du das Skript bzw. die Funktion in Bezug auf ein Fenster mit WinWaitClose() bzw. WinWait() anhalten, je nachdem ob du darauf wartest das es geschlossen bzw. geöffnet wird.
    Während es wartet ist es jedoch nicht mehr ansprechbar.

    Damit die UIs weiterhin funktionieren, musst du die betreffende Funktion z.B. mit AdlibRegister() aufrufen (und mit AdlibUnRegister() am Ende schließen), sodass der Rest des Skriptes weiterhin ausgeführt werden kann:


    Nö-Nö

    Im OnEvent Mode braucht es genau wie im MsgMode eine Endlosschleife um das Skript am Laufen zu halten. Ein einziger Blick in irgendein beliebiges GUI-Bsp. der Hilfe hätte das auch gezeigt.


  • Im OnEvent Mode braucht es genau wie im MsgMode eine Endlosschleife um das Skript am Laufen zu halten. Ein einziger Blick in irgendein beliebiges GUI-Bsp. der Hilfe hätte das auch gezeigt.


    Natürlich braucht es eine Endlosschleife, dennoch würde das UI nicht reagieren, wenn das Skript z.B. mit WinWait() "pausiert".

    Und wenn ich mir meinen Text erneut durchlese, sehe ich nicht, an welcher Stelle ich dem widersprochen hätte. :/

  • Danke Jungs, diese Interrupting a running function https://www.autoitscript.com/wiki/Interrupt…unning_function und Managing Multiple GUIs https://www.autoitscript.com/wiki/Managing_Multiple_GUIs Geschichte kann je nach Situation echt kompliziert werden. Habe zum Glück zu meiner Situation eine passende Lösung gefunden, inspiriert habe ich mich dabei an _ArrayDisplay().

    [autoit]

    #include-once

    [/autoit][autoit][/autoit][autoit]

    Func SuccessesErrorsGUI($gui, $oErrorList, $oSuccessList)

    [/autoit][autoit][/autoit][autoit]

    #Region - Take Screenshot
    _GDIPlus_Startup()
    Local $hBmp = _ScreenCapture_CaptureWnd("", $gui, 0, 0, -1, -1, False) ; create screenshot of gui without cursor
    Local $hBitmap = _GDIPlus_BitmapCreateFromHBITMAP($hBmp)
    Local $iX = _GDIPlus_ImageGetWidth($hBitmap)
    Local $iY = _GDIPlus_ImageGetHeight($hBitmap)
    Local $hResizedBitmap = _GDIPlus_ImageResize($hBitmap, $iX-($iX*0.65), $iY-($iX*0.65))

    [/autoit][autoit][/autoit][autoit]

    ; release data
    _GDIPlus_BitmapDispose($hBitmap)
    _WinAPI_DeleteObject($hBmp)
    #EndRegion - Take Screenshot

    [/autoit][autoit][/autoit][autoit]

    Local $hGUI = GUICreate("Show Successes/Errors", 240, 130 ,-1, -1) ; will create a dialog box that when displayed is centered
    Local $oSuccessesErrors = ObjCreate("Scripting.Dictionary")
    $oSuccessesErrors.add("bExpand", False)
    $oSuccessesErrors.add("hBitmap", $hResizedBitmap)
    Local $oCoord = _Coord_GetDimensions($hGUI, 0, True) ; get proper coordinates
    Opt("GUICoordMode", 1) ; absolute position
    Local $idSuccessButton = GUICtrlCreateButton("Successes", $oCoord("g1_left"), 10, 180, 50, $BS_COMMANDLINK)
    _GUICtrlButton_SetImage(_GUIGetLastCtrlID(), "ieframe.dll", 38, False)
    _GUICtrlButton_SetNote(_GUIGetLastCtrlID(), "Count: " & $oSuccessList.Count)
    GUICtrlSetResizing(-1, $GUI_DOCKALL)
    Opt("GUICoordMode", 2) ; relative to cell mode
    Local $idErrorButton = GUICtrlCreateButton("Errors", -1, 10, 180, 50, $BS_COMMANDLINK)
    _GUICtrlButton_SetImage(_GUIGetLastCtrlID(), "imageres.dll", 93, False)
    _GUICtrlButton_SetNote(_GUIGetLastCtrlID(), "Count: " & $oErrorList.Count)
    GUICtrlSetResizing(-1, $GUI_DOCKALL)
    GUISetState(@SW_SHOW)

    [/autoit][autoit][/autoit][autoit]

    ; switch to GetMessage mode
    Local $iOnEventMode = Opt("GUIOnEventMode", 0)
    Local $iMsg, $oSuccessesErrorsList

    [/autoit][autoit][/autoit][autoit]

    $oSuccessesErrors.add("idPrevButton", 0)
    $oSuccessesErrors.add("idNextButton", 0)
    $oSuccessesErrors.add("idEdit", 0)
    $oSuccessesErrors.add("sText", 0)

    [/autoit][autoit][/autoit][autoit]

    While 1
    $iMsg = GUIGetMsg()
    Switch $iMsg
    Case $idSuccessButton
    $oSuccessesErrorsList = $oSuccessList
    $oSuccessesErrors("sText") = "Successes"
    ResizeGUI($oSuccessesErrors)
    Case $idErrorButton
    $oSuccessesErrorsList = $oErrorList
    $oSuccessesErrors("sText") = "Errors"
    ResizeGUI($oSuccessesErrors)
    Case $oSuccessesErrors("idPrevButton")
    If IsHWnd(GUICtrlGetHandle($oSuccessesErrors("idPrevButton"))) Then ToggleMsg($oSuccessesErrors, $oSuccessesErrorsList, -1)
    Case $oSuccessesErrors("idNextButton")
    If IsHWnd(GUICtrlGetHandle($oSuccessesErrors("idNextButton"))) Then ToggleMsg($oSuccessesErrors, $oSuccessesErrorsList, 1)
    Case -3
    ExitLoop
    EndSwitch
    WEnd

    [/autoit][autoit][/autoit][autoit]

    ; clear up
    GUIDelete($hGUI)
    Opt("GUIOnEventMode", $iOnEventMode) ; reset original GUI mode
    EndFunc

    [/autoit][autoit][/autoit][autoit]

    Func ResizeGUI(ByRef $oSuccessesErrors)
    If $oSuccessesErrors("bExpand") = False Then ExpandGUI($oSuccessesErrors, Ptr($oSuccessesErrors("hBitmap"))) ; expand GUI first time
    $oSuccessesErrors("bExpand") = True
    #Region - Reset toggle data
    _Dict_UpdateSetKey($oSuccessesErrors, "iIndex", 0)
    _Dict_UpdateSetKey($oSuccessesErrors, "iLastDirection", 0)
    #EndRegion - Reset toggle data
    GUICtrlSetData($oSuccessesErrors("idGroup"), $oSuccessesErrors("sText")) ; update group text
    GUICtrlSetData($oSuccessesErrors("idEdit"), "") ; reset edit text
    EndFunc

    [/autoit][autoit][/autoit][autoit]

    Func ExpandGUI(ByRef $oSuccessesErrors, $hBitmap)
    WinMove("", "", Default, Default, 430, 500)
    Local $iTHICKFRAME = 7 ; border of thickframe
    Local $oCoord = _Coord_GetDimensions(WinGetHandle("", ""), 0, True) ; get proper coordinates of resized window
    $oSuccessesErrors.add("idGroup", GUICtrlCreateGroup("", -1, 50, $oCoord("g1_width"), $oCoord("GuiClient_height")-50*2-10-10-50-$oCoord("ctrl_s2")*2-35))
    Local $aPos = ControlGetPos("", "", _GUIGetLastCtrlID())
    $oSuccessesErrors("idPrevButton") = GUICtrlCreateButton("", -1, $oCoord("ctrl_s2"), 35, 35, $BS_COMMANDLINK)
    _GUICtrlButton_SetImage(_GUIGetLastCtrlID(), "wmploc.dll", 201)
    $oSuccessesErrors("idNextButton") = GUICtrlCreateButton("", $oCoord("g1_width")-35*2, -1, 35, 35, $BS_COMMANDLINK)
    _GUICtrlButton_SetImage(_GUIGetLastCtrlID(), "wmploc.dll", 200)
    Opt("GUICoordMode", 1) ; absolute position
    Local $iWidth = _GDIPlus_ImageGetWidth($hBitmap) ; get new width
    Local $iHeight = _GDIPlus_ImageGetHeight($hBitmap) ; get new height
    Local $hBmp = _GDIPlus_BitmapCreateHBITMAPFromBitmap($hBitmap) ; convert bitmap object to bitmap handle
    Local $idPic = GUICtrlCreatePic("", $oCoord("g1_width")+$oCoord("g1_left")-$iWidth-$iTHICKFRAME*2, 10, $iWidth, $iHeight, $WS_THICKFRAME)
    GUICtrlSendMsg(-1, $STM_SETIMAGE, $IMAGE_BITMAP, $hBmp)
    $oSuccessesErrors("idEdit") = GUICtrlCreateEdit("", $oCoord("g2_left"), $aPos[1]+$oCoord("g1_top"), $oCoord("g1_width")-$oCoord("g2_left"), $aPos[3]-$oCoord("g1_top")*2, _
    BitOR($ES_WANTRETURN,$WS_BORDER))

    [/autoit][autoit][/autoit][autoit]

    ; release data
    _GDIPlus_BitmapDispose($hBitmap)
    _WinAPI_DeleteObject($hBmp)
    _GDIPlus_Shutdown()
    EndFunc

    [/autoit][autoit][/autoit][autoit]

    Func ToggleMsg(Byref $oSuccessesErrors, $oSuccessesErrorsList, $iDirection)
    If $oSuccessesErrors("iLastDirection") = $iDirection And $oSuccessesErrors("iIndex")+$iDirection >= $oSuccessesErrorsList.Count Then Return ; if out of index
    If $oSuccessesErrors("iIndex")+$iDirection < 0 Then Return
    If $oSuccessesErrors("iLastDirection") <> 0 Then $oSuccessesErrors("iIndex")+=$iDirection ; chnage index second time
    GUICtrlSetData($oSuccessesErrors("idEdit"), $oSuccessesErrorsList.Item($oSuccessesErrors("iIndex"))) ; override message with new message
    $oSuccessesErrors("iLastDirection") = $iDirection
    EndFunc

    [/autoit]

    Schickes GUI, was in einer OnEvent Funktion aufgerufen (hier nicht mit aufgeführt) wird und auf Interaktion wartet. Wird die GUI geschlossen werden die restlichen Befehle in der Funktion abgearbeitet. Außerhalb der GUI ist der OnEventMode nach wie vor aktiv.

    @Matricus Die GUI vorher zu laden halte ich für ineffizient. (Offtopic) Ich denke dabei gerade an eine javascript library, die ich in meine Seite einbinden möchte, die aber nur an bestimmten Stellen eingebunden werden sollen und nicht bei jedem Seitenaufruf -> ineffizient. :huh:

    2 Mal editiert, zuletzt von Trolleule1337 (31. Oktober 2014 um 03:00)