GUI-Referenz - MessageLoop Modus

Im MessageLoop Modus wird dein Skript die meiste Zeit in einer engen Schleife verbringen. Diese Schleife wird einfach permanent die GUI mit der GUIGetMsg Funktion abfragen. Wenn ein Ereignis eingetreten ist, zeigt der Rückgabewert der GUIGetMsg Funktion die Details (ein Button wurde angeklickt, die GUI wurde geschlossen, etc.).

Der MessageLoop Modus ist der voreingestellte (Default) Nachrichtenmodus für AutoIt GUIs - der andere mögliche Modus ist der OnEvent Modus.

Im MessageLoop Modus wirst du nur von Ereignissen erfahren während du aktiv die GUIGetMsg Funktion aufrufst; deshalb musst du dafür sorgen, dass du sie mehrmals pro Sekunde aufrufst, sonst wird deine GUI nicht reagieren.

Grundlegendes MessageLoop Format

Der allgemeine MessageLoop Code siehst folgendermaßen aus:

@@SyntaxHighlighting@@ Local $iMsg = 0 While 1 $iMsg = GUIGetMsg() ... ... WEnd @@End@@

 

Normalerweise würde so eine Schleife die CPU zu 100% auslasten - glücklicherweise lässt die GUIGetMsg Funktion die CPU automatisch im Leerlauf laufen solange keine Ereignisse warten. Schreibe keinen Sleep-Befehl in die Schleife aus Angst, die CPU auszulasten - das wird nur dazu führen, dass die GUI nicht mehr auf den Nutzer reagiert.

GUI Events

Es gibt 3 Typen von Ereignis-Nachrichten, die GUIGetMsg zurückgeben kann:

Kein Ereignis

Wenn keine Ereignisse darauf warten, verarbeitet zu werden, gibt GUIGetMsg den Wert 0 zurück. In einer normalen GUI ist das das häufigste Ereignis.

Control-Ereignis

Wenn ein Control angeklickt wird oder sein Wert verändert wird, wird ein Control-Ereignis gesendet - dieses Ereignis ist eine positive Zahl, die mit der Control-ID übereinstimmt, die beim Erstellen des Controls mit GUICtrlCreate... zurückgegeben wurde.

System-Ereignis

System-Ereignisse - wie das Schließen der GUI - sind negative Zahlen. Die verschiedenen Ereignisse werden unten aufgelistet und sind in GUIConstantsEx.au3 definiert:

@@SyntaxHighlighting@@ $GUI_EVENT_CLOSE $GUI_EVENT_MINIMIZE $GUI_EVENT_RESTORE $GUI_EVENT_MAXIMIZE $GUI_EVENT_PRIMARYDOWN $GUI_EVENT_PRIMARYUP $GUI_EVENT_SECONDARYDOWN $GUI_EVENT_SECONDARYUP $GUI_EVENT_MOUSEMOVE $GUI_EVENT_RESIZED $GUI_EVENT_DROPPED @@End@@

Beispiel-GUI

Auf der Hauptseite der GUI Referenz haben wir mit einem einfachen "Hallo Welt!" Beispiel angefangen, das so aussah:

@@SyntaxHighlighting@@ #include GUICreate("Hallo Welt", 200, 100) GUICtrlCreateLabel("Hallo Welt! Wie geht's?", 30, 10) GUICtrlCreateButton("OK", 70, 50, 60) GUISetState(@SW_SHOW) Sleep(2000) @@End@@

 

Jetzt vervollständigen wir den Code mit einer MessageLoop und einigen der oben beschriebenen Ereignis-Nachrichten (Messages). Es ist üblich, wegen der Vielzahl der möglichen Nachrichten einen Switch-Ausdruck der besseren Lesbarkeit wegen zu verwenden.

@@SyntaxHighlighting@@ #include #include Local $hGUI = GUICreate("Hallo Welt", 200, 100) GUICtrlCreateLabel("Hallo Welt! Wie geht's?", 30, 10) Local $iOKButton = GUICtrlCreateButton("OK", 70, 50, 60) GUISetState(@SW_SHOW, $hGUI) Local $iMsg = 0 While 1 $iMsg = GUIGetMsg() Switch $iMsg Case $iOKButton MsgBox($MB_SYSTEMMODAL, "GUI Event", "Du hast auf OK geklickt.") Case $GUI_EVENT_CLOSE MsgBox($MB_SYSTEMMODAL, "GUI Event", "Du hast auf CLOSE geklickt. Programm wird beendet...") ExitLoop EndSwitch WEnd GUIDelete($hGUI) @@End@@

So einfach ist das. Offensichtlich wird es umso komplizierter, je mehr Fenster und Controls du anlegst, aber das Beispiel zeigt dir die Grundlagen.

GUIGetMsg für Fortgeschrittene und mehrere Fenster

Control-IDs sind eindeutig, auch wenn du mehrere Fenster hast; deshalb funktioniert der obenstehende Code gut mit Controls und mehreren Fenstern. Wenn du jedoch Ereignisse wie $GUI_EVENT_CLOSE oder $GUI_MOUSEMOVE verarbeiten willst, musst du wissen, welches GUI-Fenster das Ereignis ausgelöst hat. Dazu musst du GUIGetMsg folgendermaßen aufrufen:

@@SyntaxHighlighting@@ $iMsg = GUIGetMsg(1) @@End@@

Wenn die Funktion mit dem Parameter 1 aufgerufen wird, gibt sie statt dem Ereigniswert ein Array zurück, das das Ereignis ( in $aArray[1] ) und zusätzliche Information wie den Handle des Fensters beinhaltet ( in $array[1] ). Wenn im vorhergehenden Beispiel zwei Fenster angelegt worden wären, wäre die korrekte Schreibweise für den Code:

@@SyntaxHighlighting@@ #include #include Local $hMainGUI = GUICreate("Hallo Welt", 200, 100) GUICtrlCreateLabel("Hallo Welt! Wie geht's?", 30, 10) Local $iOKButton = GUICtrlCreateButton("OK", 70, 50, 60) Local $hDummyGUI = GUICreate("Dummy-Fenster zum Testen", 200, 100) GUISwitch($hMainGUI) GUISetState(@SW_SHOW) Local $aMsg = 0 While 1 $aMsg = GUIGetMsg(1) Select Case $aMsg[0] = $iOKButton MsgBox($MB_SYSTEMMODAL, "GUI Event", "Du hast auf OK geklickt!") Case $aMsg[0] = $GUI_EVENT_CLOSE And $aMsg[1] = $hMainGUI MsgBox($MB_SYSTEMMODAL, "GUI Event", "Du hast auf CLOSE im Hauptfenster geklickt! Programm wird beendet...") ExitLoop EndSelect WEnd @@End@@

 

Die erste große Änderung ist der Aufruf der GUISwitch Funktion - wenn ein neues Fenster angelegt wird, wird es das "default"-Fenster für zukünftige GUI-Operationen (einschließlich des Anlegens von Controls). In unserem Fall wollen wir mit dem Hauptfenster "Hello World" arbeiten, nicht mit dem Testfenster, deshalb schalten wir um ( "Switch"). Manche GUI-Funktionen erlauben dir, den Fenster-Handle im Funktionsaufruf selbst zu benutzen - diese Funktionen werden also automatisch umschalten. In unserem Beispiel hätten wir das so machen können:

@@SyntaxHighlighting@@ GUISetState(@SW_SHOW, $hMainGUI) @@End@@

 

Die zweite Änderung ist die Art, wie GUIGetMsg aufgerufen wird und wie die Ereignisse abgefragt werden - achte auf die Verwendung von $msg[0] und $msg[1] - jetzt wird das Skript nur beendet wenn das Close-Ereignis gesendet wird und das Ereignis vom Hauptfenster stammt.