=============== = Rechtliches = =============== Das hier vorgestellte Tutorial ist geistiges Eigentum des Autors mit dem Alias "Manuel". Es ist erlaubt, dieses Tutorial auch auf andere Seiten als vom Autor vorgesehen zu veröffentlichen, allerdings dann (und NUR dann), wenn das Tutorial nicht verändert wird und jederzeit ersichtlich ist, dass das Tutorial von "Manuel" und nicht von jemand anderem geschrieben wurde. Jegliche Veröffentlichungen dieses Tutorials komplett oder in Auszügen, die oben genanntes widersprechen, sind nicht erlaubt! --- GUI-Programmierung für Einsteiger - Tutorial 1. Vorwort 2. Unser zweites GUI-Programm 2.1 Vorüberlegungen & die Oberfläche --- --- 2.2a Benutzereingaben: Die "MessageLoop"-Methode 2.2b Benutzereingaben: Die "OnEvent"-Methode 3. Sonstiges & Nachwort =========== = Vorwort = =========== AutoIt ist ja - wie man in manchen Zeitschriften und Foren nachlesen kann - eine Skriptsprache, mit dem man auf einfache Weise automatisierte Installationsroutinen erstellen kann. Dank eines einfachen Tutorials bei der AutoIt-Hilfe und der kompetenten Übersetzung der deutschsprachigen AutoIt-Community kann jeder halbwegs versierte Computernutzer einfache Installationsskripte auch selbst schreiben. AutoIt kann aber noch mehr: Es kann so genannte GUI-Anwendungen (Graphical User Interface, zu Deutsch: Grafische Benutzeroberflächen) erstellen. Wie das ausgesprochene Kürzel schon sagt, lassen sich mit AutoIt Anwendungen erstellen, mit dem der (Computer-)Nutzer interagieren kann, beispielsweise Schaltflächen anklicken oder Ähnliches. Zu meinem Bedauern musste ich jedoch feststellen, dass das Erstellen von GUIs - im Gegensatz zu Installationsskripten - in der AutoIt-Hilfe vergleichsweise unzureichend erklärt wird. Während man für die Installation eines Programms (in der Hilfe ist es das "WinZip") quasi an die Hand genommen und jeder Schritt erklärt wird, muss man sich für eine anständige GUI-Entwicklung schon mal kreuz und quer durch die Hilfe klicken. Weswegen Installationsroutinen geschrieben werden, ist wohl jedem klar, aber die Anwendung von GUI-Programmen erschließt sich zumindest dem Anfänger nicht, wenn er die Hilfe liest. Es wird kein "Einsatzgebiet" von GUI-Anwendungen beschrieben, lediglich die absoluten Grundzüge werden erläutert. Will man allerdings wissen, wie sich der Inhalt z. B. eines Textlabels auslesen oder verändern lässt, stößt man mangels Code-Schnipsel schon an die Grenzen der Hilfe. Da hilft wohl oder übel nur Ausprobieren oder ausgiebiges Durchsuchen der Hilfe, da entsprechende Erläuterungen kreuz und quer "versteckt" sind. In diesem Punkt setzt das Tutorial an: Es will den Verwendungszweck von GUI-Programmen erklären und es will zeigen, was man mit AutoIt noch so alles anstellen kann, außer Skripte für Installationen zu erstellen. AutoIt hat nicht umsonst das Potential, um damit kleinere Spiele ("Vier Gewinnt", "Mastermind", "Schach"...) oder nützliche Utilities ("XP-Antispy"-Kopie...) erstellen zu können. Ein Hinweis gleich vorneweg: Ich gehe hier nicht allzu tief in Materien ein, die nicht bereits schon vorher in der AutoIt-Hilfe erklärt werden. Sollte man sich von dem Tutorial also erhoffen, dass endlich mal die Funktionsweise von Variablen erklärt werden, dem wird dieses Tutorial wahrscheinlich nicht weiterhelfen können^^. Die "Denkweise des Programmierers" oder meinetwegen auch "Skripters" muss man für das Verständnis dieses Tutorials mitnehmen :) . Was z. B. Parameter von Befehlen oder Zuweisungs- und Vergleichsoperatoren sind, setze ich genauso wie IF- und Select-Strukturen voraus! ============================== = Unser zweites GUI-Programm = ==|=========================== Zu Recht wird hier die Nase gerümpft, wenn man sich die Überschrift ansieht. Das hat allerdings seinen Grund: Ich will an dieser Stelle voraussetzen, dass man zumindest schon einen Blick unter dem Punkt "GUI-Referenz" -> "GUI-Konzepte" geworfen und das dort genannte Beispiel ausprobiert hat. Deswegen wird in diesem Unterpunkt unsere zweite statt erste GUI-Anwendung erstellt. Ansonsten können wir sofort loslegen^^. =|=================================== => Vorüberlegungen & die Oberfläche = ==|================================== Zuerst soll man sich Gedanken darüber machen, WAS für ein Programm mit GUI-Elementen wir überhaupt erstellen wollen. Die AutoIt-Hilfe bringt uns nicht weiter, da dort kaum Verwendungszweck für eine GUI erläutert wird. Also müssen wir selbst einen Verwendungszweck für GUI-Anwendungen herausfinden. Nun denn, ein einfaches Projekt, welches uns die Grundzüge der GUI-Erstellung erläutern würde, wäre zweifelsohne ein einfacher Taschenrechner. Damit muss zumindest ein Verwendungszweck für die Überprüfung und Bearbeitung von Zahlen herhalten. Natürlich könnte man die Zahlen im Quellcode hinterlegen, doch was wäre gewonnen? Wir wollen schließlich, dass der Benutzer die Zahlen eingibt und selbst bestimmen kann. Für den Anfang genügt es, wenn der Benutzer lediglich zwei Zahlen angeben muss. Danach soll der Benutzer die Wahl haben, was er mit den Zahlen anfangen soll: Sollen sie addiert, subtrahiert, multipliziert oder dividiert werden? Sobald der Benutzer die Wahl getroffen hat, soll - natürlich - das Ergebnis der Addition, Subtraktion... angezeigt werden. So, wir hätten nun einen Grundgedanken und wissen genau, was wir mit dem Programm wollen! Also dann, frisch ans Werk. Erstellen wir zuallererst ein Fenster, in dem unser Taschenrechnerprogramm ablaufen soll: #include GUICreate ("Taschenrechner", 200,250) (Hinweis: Die Koordinaten "200" und "250" beim "GUICreate"-Befehl sind - wie fast alle anderen Größenkoordinaten - für unser Programm optimal zugeschnitten. Selbstverständlich muss beim Entwickeln hin und wieder ausprobiert werden, welche Koordinaten für so ein vergleichsweise kleines Programm nötig sind.) Die erste Zeile sollte noch von der AutoIt-Hilfe im Kopf sein: Das Einbinden der "GUIConstants.au3" ist nötig, damit wir überhaupt GUI-Anwendungen erstellen können. Es "erlaubt" quasi die Befehle, die man benötigt um GUI-Anwendungen zu erstellen. Die zweite Zeile erschafft, wie (hoffentlich) gehabt, ein Fenster mit dem Titel "Taschenrechner" mit 200 Pixel Breite und 250 Pixel Höhe. Selbstverständlich war das noch nicht alles ;) . Jetzt sollte man sich Gedanken machen, wie das Programm überhaupt auszusehen hat. Im Vordergrund steht an dieser Stelle der Entwicklung, wie der Benutzer seine Zahlen eingeben soll. Natürlich könnte man für jede Zahl einen eigenen Button erstellen - der Windows-Taschenrechner lässt grüßen. Viel einfacher und auch weniger aufwendig wäre, wenn man stattdessen "Eingabefelder", so genannte Texteingabe- oder Editfelder, benutzen würde. Also erstellen wir zwei Editfelder. Der Übersichtlichkeit halber erstellen wir auch noch zwei so genannte Labels, in dem beschrieben wird, was in den zwei Editfeldern überhaupt reingehört: GUICtrlcreatelabel ("Erste Zahl",10,15) GUICtrlcreatelabel ("Zweite Zahl",100,15) GUICtrlCreateEdit ("", 163,10,25,20,0) GUICtrlCreateEdit ("", 65,10,25,20,0) Ok, damit hätten wir schon zwei Paar Editfelder. Der letzte Parameter "0" bei beiden "GUICtrlCreateEdit"-Befehlen sorgt dafür, dass man die Felder - entgegen der Standardeinstellung - nicht horizontal oder vertikal in einem Editfeld scrollen kann. Das würde nicht nur unschön aussehen, sondern hätte auch wenig Nutzen; was soll der Benutzer rechnen, wenn er drei- oder viermal oder noch öfter ENTER drücken könnte? (genauere Informationen, warum das so ist, findet man in der AutoIt-Hilfe.) Jetzt müssen wir mal kurz vorausschauend denken: Die Zahlen, die der Benutzer später in die beiden Editfelder eingeben wird, müssen irgendwie erfasst oder ausgelesen werden. Das machen so genannte ControlIDs, wie die AutoIt-Hilfe es nennt. Leider wird in der Hilfe nicht ersichtlich, wie die ControlIDs vergeben werden. Glücklicherweise müssen wir das auch nicht herausfinden, da wir genannte ControlID ohne Probleme einer Variable zuweisen können. Wie gesagt, brauchen wir die ControlID der beiden Editfelder, damit wir deren vom Benutzer eingegebene Zahlen einlesen können. Da wir - ebenfalls wie gesagt - sowas in Variablen speichern können, müssen wir die letzten beiden eingegebenen Zeilen so abändern, dass die ControlIDs der beiden Editfelder auch in Variablen gespeichert werden. Kurz: Das obige genannte Listing ist (was die letzten beiden Zeilen angeht) falsch, richtig wäre: GUICtrlcreatelabel ("Erste Zahl",10,15) GUICtrlcreatelabel ("Zweite Zahl",100,15) $number1 = GUICtrlCreateEdit ("", 65,10,25,20,0) $number2 = GUICtrlCreateEdit ("", 163,10,25,20,0) Für die beiden Labels sind natürlich keine Variablen notwendig. Was sollen wir schon später im Programmablauf daran ändern wollen? Ansonsten sticht die Änderung sofort ins Auge: Variable $number1 bekommt die sog. ControlID vom ersten Editfeld, $number2 die ControlID vom zweiten Editfeld. Damit können wir später auslesen, welche Werte in die Editfelder eingegeben wurden. So, jetzt soll der Benutzer entscheiden, ob er von beiden Zahlen die Summe, die Differenz... haben will. Hierfür reichen einfache Buttons aus, die - da darauf Mausklicks erfasst werden müssen - ebenfalls Variablen zugewiesen werden. Der Tradition halber bauen wir noch zusätzlich einen "Beenden"-Button ein: $addbutton = GUICtrlCreateButton (" Addieren ", 10,40) $subbutton = GUICtrlCreateButton (" Subtrahieren ", 10,70) $mulbutton = GUICtrlCreateButton ("Multiplizieren", 10,100) $divbutton = GUICtrlCreateButton (" Dividieren ", 10,130) $endbutton = GUICtrlCreateButton (" Programm Beenden ", 10,190) Jetzt fehlt an der Oberfläche nur noch der Platz, in dem das Ergebnis ausgegeben werden soll. Das Ergebnis wird - damit wir später auch die Funktionsweise erfahren, wie wir ControlIDs durch Variablen auch mal ändern anstatt nur auslesen - per Textfeld ("Label") angezeigt. Genanntes Label wird am Besten schon vor dem eigentlichen Programmablauf angelegt: GUICtrlcreatelabel ("Ergebnis:",100,60) $ergebnis = GUICtrlcreatelabel ("- keins -",150,60) Der Parameter "- keins -" wird später durch die Ergebnisse ersetzt. Das aber natürlich erst, wenn mir soweit sind :) . Die Oberfläche ist nun komplett angelegt. Nun soll sie der Benutzer natürlich auch sehen ;) : GUISetState(@SW_SHOW) Der Parameter "@SW_SHOW" ist ein System-Ereignis und sorgt dafür, dass man das Fenster, das wir so eifrig programmieren, auch mal komplett sehen ;) . Für genauere Informationen von System-Ereignissen hilft die AutoIt-Hilfe weiter. --- Für alle, die aktiv dabei sind und den Quellcode nicht ständig neu schreiben wollen, hier noch das komplette Listing, das wir bis jetzt erstellt haben: #include GUICreate ("Taschenrechner", 200,250) GUICtrlcreatelabel ("Erste Zahl",10,15) GUICtrlcreatelabel ("Zweite Zahl",100,15) $number1 = GUICtrlCreateEdit ("", 65,10,25,20,0) $number2 = GUICtrlCreateEdit ("", 163,10,25,20,0) $addbutton = GUICtrlCreateButton (" Addieren ", 10,40) $subbutton = GUICtrlCreateButton (" Subtrahieren ", 10,70) $mulbutton = GUICtrlCreateButton ("Multiplizieren", 10,100) $divbutton = GUICtrlCreateButton (" Dividieren ", 10,130) $endbutton = GUICtrlCreateButton (" Programm Beenden ", 10,190) GUICtrlcreatelabel ("Ergebnis:",100,60) $ergebnis = GUICtrlcreatelabel ("- keins -",150,60) GUISetState(@SW_SHOW) Ok, die Oberfläche hätten wir nun endgültig fertig. Was fehlt, ist jetzt der Hauptteil der Programmierung. In diesem Hauptteil müssen nun die Benutzereingaben des Benutzers (ein schönes Wortspiel^^) überprüft und ausgewertet werden. Je nachdem, was bei der Auswertung herauskommt (sprich: welche Buttons der Benutzer gedrückt hat) muss etwas Bestimmtes erledigt werden. Genauer: Wenn der Benutzer z. B. auf den Button "Addieren" klickt, sollen die beiden Zahlen in den Editfeldern addiert und das Ergebnis ausgegeben werden. Das Gleiche gilt für alle anderen Buttons, die wir an der Oberfläche angebracht haben. Da es in AutoIt zwei verschiedene Varianten gibt, wie man dieses Problem lösen kann, will ich dementsprechend auch beide Methoden verwenden. Mir persönlich ist die "MessageLoop"-Methode (eine der beiden Varianten) lieber, aber ich will niemanden zwingen, dass er sich nur einen der beiden möglichen Wege ansieht. Keine Sorge: Kurz vor Schluss der beiden Unterpunkte wird das komplette Listing beider Methoden in ihrer eigenen Variante nochmal angezeigt. Nun denn, in den folgenden Unterpunkten geht es jetzt ans Eingemachte. =|============================================== => Benutzereingaben: Die "MessageLoop"-Methode = =|============================================== Die "MessageLoop"-Methode ist relativ einfach und wird einem BASIC-Veteranen nach kurzer Eingewöhnungszeit schnell bekannt vorkommen. Was wir zuallererst brauchen, sind Schleifen. Eine Schleife ist - Hobbyprogrammierer/-Skripter wissen es schon längst - Programmteile, die ständig wiederholt werden, bis ein bestimmtes, vom Programmierer/Skripter gesteuertes Ereignis eintritt. Schließlich soll der Benutzer nicht sofort nach dem Bruchteil einer Sekunde, nachdem das Programm gestartet wurde, sofort einen Button anklicken müssen (sonst beendet sich das Programm binnen 0,1 Sekunde, weil der Code durchgearbeitet wurde :D ). Die in der AutoIt-Hilfe erwähnte "While-Wend"-Schleife werden wir zu diesem Zweck auch nicht ändern. Anders ausgedrückt: Diese Schleife wird verwendet, um unseren Programmcode zu überprüfen. While 1 Nun brauchen wir eine Variable, die speichert, ob eine ControlID vom Benutzer ausgewählt wurde (auf Deutsch: Welcher Button gedrückt wurde). WAS der ControlID für einen Wert hat, braucht uns nicht interessieren, da wir ja alle relevanten in Variablen abgespeichert haben. Außerdem gibt es zum Glück eine Funktion, die herausfindet, welche ControlID vom Benutzer gerade gewählt wurde (sprich: Welchen Button der Benutzer gerade drückt). Diese Funktion heißt "GUIGetMsg". Solange diese Funktion den Wert (wie bei einer Variable) "0" hat, wurde nichts gedrückt. Man könnte die Funktion direkt nach dem Wert abfragen (dazu später), allerdings würde sie nach der Abfrage wieder den Wert "0" erhalten, sobald der Benutzer die linke Maustaste loslässt und damit nicht mehr auf den Button klickt. Also müssen wir, solange die Funktion noch die ControlID des gedrückten Buttons gespeichert hat, einer anderen Variable zuweisen. Nennen wir diese Variable $msg: $msg = GUIGetMsg() Was wir jetzt brauchen, ist eine Abfrage, welchen Wert $msg hat. Wenn er "0" hat, soll er nichts machen. Anders ausgedrückt, wenn $msg einen anderen Wert als "0" hat, muss was passiert sein. Dies prüfen wir mit einer IF-Bedingungsklausel (näheres dazu in der AutoIt-Hilfe): If $msg <> 0 Then (Ein kurzer Hinweis, wie er schon im Vorwort zu finden war. Ich setze in diesem Tutorial voraus, was eine IF-Anweisung und deren "Verwandter" Select (dazu später mehr) ist. Die AutoIt-Hilfe gibt in diesem Punkt mehr Informationen aus sich heraus.) Um diese Codezeilen in menschliche Worte zu fassen: "Wenn Variable $msg alles andere als Wert 0 hat, führe folgendes aus". WAS soll als Folgendes ausgeführt werden? Gute Frage... Alles, was nach dieser IF-Klausel kommt, wird gemacht, wenn der Benutzer einen Button angeklickt hat (Also wissen wir: Der Benutzer hat einen Button angeklickt). Ob der Benutzer jetzt den Button für "Subtrahieren" oder "Dividieren" gedrückt hat ist (vorerst) irrelevant. Erstmal müssen die Zahlen, die er (hoffentlich) vorher in die beiden Editfelder eingegeben hat, in Variablen gespeichert werden. wie im vorigen Unterpunkt gezeigt wurde, haben wir aber immerhin die ControlIDs der beiden Editfelder. Dank der Funktion "GUICtrlRead" dürfte das kein Problem sein: Diese Funktion dient dazu, den Inhalt eines ControlIDs auszulesen. Die Funktion ist also genau das, was wir für unsere beiden Editfelder brauchen! Als Parameter (siehe AutoIt-Hilfe) für diese Funktion wird zwar eine ControlID verlangt, aber diese haben wir sowieso in $number1 und $number2 gespeichert. Also speichern wir in zwei neuen Variablen den Inhalt der ControlIDs (also der Editfelder): $zahl1 = GUICtrlRead($number1) $zahl2 = GUICtrlRead($number2) Ok, beide Variablen sind gespeichert. Jetzt (besser gesagt: Jetzt erst!) muss noch überprüft werden, welchen Button der Benutzer überhaupt angeklickt hat. Das erledigen wir per Select-Abfrage: Select Select ist ein etwas übersichtlicherer "Verwandter" von IF, wobei in Sachen Hilfe das Gleiche gilt: Die AutoIt-Hilfe gibt da mehr Auskunft. Da wir nun wissen, wie wir ControlIDs Variablen zuweisen können, können wir sie auch problemlos mit der Select-Verschachtelung überprüfen und dementsprechend handeln (also Zahlen addieren, subtrahieren...). Das Problem dabei ist allerdings: Wie kann man den Inhalt der ControlID von der Variable $ergebnis , die (sinnigerweise) das Ergebnis speichert, ändern? Vorsicht, hier liegt ein Stolperstein: Versucht NICHT, die Variable $ergebnis zu ändern, den sie enthält lediglich die ControlID, der zum Inhalt führt, jedoch NICHT den Inhalt selbst. Was nun? Nun, wie es eine Funktion für das Einlesen von ControlID-Inhalten gibt, so gibt es auch eine Funktion für das Ändern ("Schreiben") von ControlID-Inhalten: "GUICtrlSetData". Genau wie "GUICtrlRead" wird als Parameter eine ControlID benötigt... Die ControlID, die wir in der Variable $ergebnis gespeichert haben! Jetzt können wir durch die Case-Verschachtelung, die bei Select dabei ist, den gedrückten Button überprüfen und dementsprechend handeln. Hier das Beispiel, wenn der "Addition"-Button gedrückt wurde: Case $msg = $addbutton GUICtrlSetData ($ergebnis, $zahl1 + $zahl2) Die erste Zeile ist wie eine IF-Abfrage: "Wenn Variable $msg den gleichen Wert wie Variable $addbutton hat, führe folgendes aus". In der nächsten Zeile wird der Inhalt von irgendeiner ControlID geändert. Pardon, ich meine: Der Inhalt der ControlID, die den Wert der Variable $ergebnis hat. Wie gesagt, WELCHER ControlID das ist, ist wurscht. Auf alle Fälle kriegt der ControlID-Inhalt vom $ergebnis genau das, was in der Zeile dasteht: "$zahl1 + $zahl2". Um Missverständnisse vorzubeugen: Die Variablen $zahl1 und $zahl2 werden NICHT geändert! Es wird nur der ControlID-Inhalt von $ergebnis geändert, dieser speichert den Wert von $zahl1 + $zahl2 ab. Achja, fast hätte ich es vergessen: Die Änderung des ControlID-Inhalts $ergebnis wird nach diesem Aufruf sofort sichtbar. Es muss kein weiterer Befehl mehr für die Änderung angegeben werden. Nachdem die Funktionsweise (hoffentlich) klar geworden ist, müssen natürlich auch die anderen Buttons überprüft werden: Case $msg = $subbutton GUICtrlSetData ($ergebnis, $zahl1 - $zahl2) Case $msg = $mulbutton GUICtrlSetData ($ergebnis, $zahl1 * $zahl2) Case $msg = $divbutton GUICtrlSetData ($ergebnis, $zahl1 / $zahl2) Ok, damit wäre wir fer... Halt! Haben wir nicht noch einen "Beenden"-Button eingebaut? Case $msg = $endbutton Or $msg = $GUI_EVENT_CLOSE ExitLoop (Hinweis: Was "Or" bedeutet, ist es besser, in der AutoIt-Hilfe nachzusehen. Kurz gesagt, wird die nächste Zeile ausgeführt, wenn nur eine der beiden Bedingungen erfüllt sind. Das "$GUI_EVENT_CLOSE" ist ein System-Ereignis... nämlich das Ereignis, was passiert, wenn der Benutzer auf das "X"-Knöpfchen oben rechts im Fenster drückt. Nochmal kurz gesagt: "Wenn "Beenden"- ODER "X"-Button gedrückt wurde, soll folgendes ausgeführt werden...".) Der Befehl "ExitLoop" beendet die Schleife, die wir zuvor noch mit "While 1" gesetzt haben. Wo ein Anfang, da ein Ende der Schleife: Wir haben ganz vergessen, sowohl den "Select"- als auch den "IF"-Strang und natürlich auch noch die Schleife zu schließen (bei der genauen Funktionsweise bitte auf die AutoIt-Hilfe zurückgreifen): ExitLoop EndSelect EndIf Wend Somit hätten wir ALLES beisammen für einen funktionsfähigen, kleinen "Taschen"-Rechner. Glückwunsch, du hast das Tutorial durchgearbeitet :) . Hier nochmal das komplette Listing für alle, die nicht ständig nach den richtigen Textstellen suchen wollen: #include GUICreate ("Taschenrechner", 200,250) GUICtrlcreatelabel ("Erste Zahl",10,15) GUICtrlcreatelabel ("Zweite Zahl",100,15) $number1 = GUICtrlCreateEdit ("", 65,10,25,20,0) $number2 = GUICtrlCreateEdit ("", 163,10,25,20,0) $addbutton = GUICtrlCreateButton (" Addieren ", 10,40) $subbutton = GUICtrlCreateButton (" Subtrahieren ", 10,70) $mulbutton = GUICtrlCreateButton ("Multiplizieren", 10,100) $divbutton = GUICtrlCreateButton (" Dividieren ", 10,130) $endbutton = GUICtrlCreateButton (" Programm Beenden ", 10,190) GUICtrlcreatelabel ("Ergebnis:",100,60) $ergebnis = GUICtrlcreatelabel ("- keins -",150,60) GUISetState(@SW_SHOW) While 1 $msg = GUIGetMsg() If $msg <> 0 Then $zahl1 = GUICtrlRead($number1) $zahl2 = GUICtrlRead($number2) Select Case $msg = $addbutton GUICtrlSetData ($ergebnis, $zahl1 + $zahl2) Case $msg = $subbutton GUICtrlSetData ($ergebnis, $zahl1 - $zahl2) Case $msg = $mulbutton GUICtrlSetData ($ergebnis, $zahl1 * $zahl2) Case $msg = $divbutton GUICtrlSetData ($ergebnis, $zahl1 / $zahl2) Case $msg = $endbutton Or $msg = $GUI_EVENT_CLOSE ExitLoop EndSelect EndIf Wend =|========================================== => Benutzereingaben: Die "OnEvent"-Methode = =|========================================== Die "OnEvent"-Methode unterscheidet sich etwas vom herkömmlichem und gebräuchlicherem "MessageLoop"-Befehl, da es hier - im Gegensatz zur "MessageLoop"-Methode - großteils um Funktionen als um Bedingungen geht. Im nun folgenden Unterpunkt wird das genau erklärt. Um die "OnEvent"-Methode anwenden zu können, müssen wir die Methode - im Gegensatz zur "MessageLoop"-Methode - erst freischalten. Dies erledigt der folgende Befehl: Opt("GUIOnEventMode", 1) Diese Zeile schaltet in die "OnEvent"-Methode um. Ok, nun müssen wir wieder ein wenig Vorarbeit leisten. Die Buttons für das Addieren, Subtrahieren... sind bereits gelegt. Nun erstellen wir direkt so genannte Funktionen. Diese Funktionen werden ausgeführt, wenn der Benutzer ein Ereignis auslöst (also zum Beispiel auf einen Button klickt... merkt ihr was? :D ). Diese Funktionen muss sich AutoIt allerdings erst aneignen, damit er sie verwenden kann. Im Fachjargon nennt man das "deklarieren". Funktionen deklariert man in AutoIt mit dem Befehl "GUICtrlSetOnEvent". Der erste Parameter (AutoIt-Hilfe^^) muss die ControlID der Schaltfläche sein. Aber woher wissen wir, welche ControlIDs die Schaltfläche "Addieren", "Subtrahieren"... haben? Nun, wir haben sie in Variablen eingespeichert, schon vergessen? :D Der zweite Parameter gibt an, welche Funktion aufgerufen werden soll. Da die Funktion ja noch nicht erstellt ist (das müssen wir später natürlich nachholen), kann man im Prinzip jeden beliebigen Namen wählen. Der Übersichtlichkeit halber sollte man trotzdem sinnvolle Namen verteilen, die eine Funktion schon beim Anblick des Namens sofort deren Verwendungszweck beschreibt. Erstellen wir also eine Deklaration für eine Funktion. Zuerst mal für den "Addieren"-Button... (Die ControlID wurde ja in Variable $addbutton gespeichert): GUICtrlSetOnEvent($addbutton, "Addieren") Wie gesagt: Die Funktion "Addieren", die jederzeit aufgerufen wird, sobald der Benutzer auf den Button mit dem Namen "Addieren" klickt, muss erst noch geschrieben werden. Erst deklarieren wir mal alle Funktionen, bevor es weitergeht. Hier also die restlichen Deklarationen für die restlichen Buttons (einschließlich des "Beenden"-Buttons - den haben wir doch nicht vergessen, oder? ;) ): GUICtrlSetOnEvent($subbutton, "Subtrahieren") GUICtrlSetOnEvent($mulbutton, "Multiplizieren") GUICtrlSetOnEvent($divbutton, "Dividieren") GUICtrlSetOnEvent($endbutton, "Beenden") GUICtrlSetOnEvent($GUI_EVENT_CLOSE, "Beenden") Eine kleine Sonderstellung nimmt die letzte Zeile ein: Der Parameter "$GUI_EVENT_CLOSE" ist ein System-Ereignis und tritt dann auf, wenn der Benutzer im Taschenrechner das typische, oben rechts liegende "X"-Feld anklickt. Da sowohl der "Programm beenden"-Button als auch das Windows-typische "X"-Feld oben rechts den Taschenrechner beenden sollen, wird bei beiden auch auf die gleiche Funktion (nämlich auf die Funktion "Beenden") hingewiesen. Ok, jetzt haben wir ein kleines Problem, welches noch nicht besprochen wurde: Variablen in Funktionen werden als "neue" Variablen behandelt. Wir wollen aber mit den Variablen arbeiten, die wir vorher die ControlID-Werte der Schaltflächen bzw. der Editfelder zugewiesen haben. Wie machen wir das? Hier hilft der Befehl "Global" weiter. Er sorgt dafür, dass man auf allen Funktionen, die wir noch erstellen werden, af die gleichen Variablen Zugriff hat, wie wenn man nicht in einer Funktion wäre. Nun denn, welche Variablen müssen "global" (daher der Befehlsname) eingestellt werden? Da in den Funktionen mit den Inhalten der ControlIDs der beiden Editfelder gearbeitet werden muss, definieren wir zwei globale Variablen, nämlich Variablen mit den Namen $zahl1 und $zahl2. Außerdem muss noch die Variable $ergebnis global eingestellt werden, da die Funktionen diesen Wert verändern müssen. Global $zahl1 Global $zahl2 Global $ergebnis Nun denn, was machen wir jetzt? Jetzt ist eine Schleife notwendig, die findige Hobbyprogrammierer schon längst kennen: Die "while-wend"-Schleife. In dieser Schleife soll nun das ganze Programm ablaufen. Zwischen den Befehlen "While" und "Wend" ist - was die Funktionsweise des Taschenrechners anbelangt - absolut nichts mehr nötig, da das Abrufen von Funktionen von unseren Deklarationen erledigt wird. Vorsicht: Wie in der AutoIt-Hilfe beschrieben, soll man allerdings unbedingt einen sog. "Sleep"-Befehl hineinsetzen, ansonsten steigt die Prozessorauslastung auf 100% an und hält somit alle anderen Programme auf (in der AutoIt-Hilfe wird selbiges Phänomen genau beschrieben). Vorsicht: Wir können nicht so einfach einen Sleep-Befehl zwischen den Schleifen einbauen und dann hoffen, dass das Programm läuft. Die Funktionen müssen auch noch die Zahlen bekommen, die bei den Editfeldern vom Benutzer eingegeben wurden. Wir haben zwar Variable $zahl1 und $zahl2 deklariert, aber noch keinen Wert zugewiesen. Variable $number1 und $number2 können wir nicht deklarieren, da in ihnen nur die ControlIDs der Editfelder, nicht aber der Inhalt der Editfelder zugewiesen wurde. Also müssen wir herausfinden, wie man den Inhalt einer ControlID, nicht aber die ControlID selbst, auslesen. Das erledigt für uns der Befehl "GUICtrlRead". Als Parameter wird eine ControlID benötigt, die wir allerdings einer Variable zugewiesen haben. Damit der Inhalt der ControlID auch irgendwo gespeichert wird, muss natürlich eine Variable herhalten. Dreimal dürft ihr raten, wo wir den Inhalt der ControlID speichern ;) . Natürlich in die Variablen, die wir zuvor als "global" eingestellt hatten und mit denen die Funktionen nachher arbeiten sollen: While 1 $zahl1 = GUICtrlRead ($number1) $zahl2 = GUICtrlRead ($number2) sleep (1) WEnd Damit wäre die Schleife komplett. Wie schon gesagt, ist in der vorletzten Zeile der "Sleep"-Befehl nötig, da ansonsten die Prozessorauslastung auf 100% aufsteigen würde und damit das Arbeiten z. B. nebenher mit Word unmöglich macht. Vorsicht: Der Parameter für den Sleep-Befehl sollte nicht zu hoch angesetzt werden. Der Grund ist, dass die Variablen $zahl1 und $zahl2 immer erst dann den Wert zugewiesen bekommen, wenn der sleep-Befehl "abgelaufen" ist. Ansonsten kann es passieren, dass man die Werte in den Editfeldern schon geändert hat, das Skript aber noch mit alten Zahlen rechnet, da vor der neuen Variablenzuweisung noch der Sleep-Befehl dran war. Es ist zugegebenerweise etwas blöd zu erklären, am Besten ist es, wenn man den Parameter für Sleep selbst mal auf 10000 erhöht und dann nachsieht, was passiert^^. "Sind wir fertig mit dem Skript?" Leider noch nicht :D . wir müssen noch die Funktionen, die wir vorhin deklariert hatten, erstellen. Eine Funktion beginnt mit "Func [Funktionsname]" und endet mit "EndFunc". Dazwischen müssen nun für unsere Buttons geschrieben werden, was die entsprechenden Buttons auch tun sollen, also Addieren, Subtrahieren... Nun, dank der Operatoren +, -, * und / könnten wir ohne Probleme das Ergebnis in einer Variable speichern. Das Ergebnis soll aber nicht in einer Variable gespeichert werden, sondern in dem Label, dessen ControlID wir in der Variable $ergebnis gespeichert hatten (wir erinnern uns dunkel...). Nun, bis jetzt wissen wir nur einen Befehl, um den Inhalt von ControlIDs auszulesen, nämlich GUICtrlRead. Natürlich gibt es auch einen, der die Inhalte von ControlIDs auch verändern ("schreiben") kann, und das ist der Befehl "GUICtrlSetData". Damit hätten wir alles beisammen, um eine Funktion für das Addieren zu schreiben: Func Addieren() GUICtrlSetData($ergebnis, $zahl1 + $zahl2) EndFunc Die erste und die letzte Zeile geben an, welche Funktion gerade eingestellt wird und wann diese zu Ende ist. Wir erinnern uns noch an die Deklaration: Wir hatten eingestellt, dass, sobald der "Addieren"-Button angeklickt wird, die Funktion "Addieren" ausgeführt wird. Die zweite Zeile habe ich schon erklärt: Der Inhalt der ControlID der Variable $ergebnis bekommt den Wert "$zahl1 + $zahl2". Jetzt müssen nur noch die anderen Funktionen geschrieben werden, die wir zuvor deklariert hatten: Func Subtrahieren() GUICtrlSetData($ergebnis, $zahl1 - $zahl2) EndFunc Func Multiplizieren() GUICtrlSetData($ergebnis, $zahl1 * $zahl2) EndFunc Func Dividieren() GUICtrlSetData($ergebnis, $zahl1 / $zahl2) EndFunc Func Beenden() Exit EndFunc Die Funktion "Beenden" war ja der "Beenden"-Button und gleichzeitig der "X"-Knopf im Fenster oben rechts. Der Befehl "Exit" macht genau das, wie er heißt: Er beendet das Skript. Nun haben wir das Skript endlich fertiggestellt. Das komplette Listing für die "OnEvent"-Methode wäre also: #include GUICreate ("Taschenrechner", 200,250) GUICtrlcreatelabel ("Erste Zahl",10,15) GUICtrlcreatelabel ("Zweite Zahl",100,15) $number1 = GUICtrlCreateEdit ("", 65,10,25,20,0) $number2 = GUICtrlCreateEdit ("", 163,10,25,20,0) $addbutton = GUICtrlCreateButton (" Addieren ", 10,40) $subbutton = GUICtrlCreateButton (" Subtrahieren ", 10,70) $mulbutton = GUICtrlCreateButton ("Multiplizieren", 10,100) $divbutton = GUICtrlCreateButton (" Dividieren ", 10,130) $endbutton = GUICtrlCreateButton (" Programm Beenden ", 10,190) GUICtrlcreatelabel ("Ergebnis:",100,60) $ergebnis = GUICtrlcreatelabel ("- keins -",150,60) GUISetState(@SW_SHOW) Opt("GUIOnEventMode", 1) GUICtrlSetOnEvent($addbutton, "Addieren") GUICtrlSetOnEvent($subbutton, "Subtrahieren") GUICtrlSetOnEvent($mulbutton, "Multiplizieren") GUICtrlSetOnEvent($divbutton, "Dividieren") GUICtrlSetOnEvent($endbutton, "Beenden") GUICtrlSetOnEvent($GUI_EVENT_CLOSE, "Beenden") Global $zahl1 Global $zahl2 Global $ergebnis While 1 $zahl1 = GUICtrlRead ($number1) $zahl2 = GUICtrlRead ($number2) sleep (1) WEnd Func Addieren() GUICtrlSetData($ergebnis, $zahl1 + $zahl2) EndFunc Func Subtrahieren() GUICtrlSetData($ergebnis, $zahl1 - $zahl2) EndFunc Func Multiplizieren() GUICtrlSetData($ergebnis, $zahl1 * $zahl2) EndFunc Func Dividieren() GUICtrlSetData($ergebnis, $zahl1 / $zahl2) EndFunc Func Beenden() Exit EndFunc ======================== = Sonstiges & Nachwort = ======================== Ich habe versucht, dieses Tutorial so ausführlich und verständlich wie möglich zu beschreiben. Ich habe das Tutorial bewusst in dem Wissen erstellt, dass ich bereits Vorkenntnisse vor allem von Funktionen und IF-/Select-Klauseln voraussetze. Mir ist es beim Schreiben dieses Tutorials vor allem darum gegangen, das Potential einer richtigen Programmiersprache von AutoIt herauszukitzeln. Mir ist natürlich bewusst, dass die hier vorgestellte Lösung nur eine von vielen ist. Natürlich hätte man z. B. die Buttons mit Radio- oder Textboxen ersetzen können. Auch wurden einige Punkte nicht behandelt, beispielsweise was passiert, wenn man in den Editfeldern Buchstaben statt Zahlen eingibt oder durch 0 dividiert. (Was allerdings Absicht ist: Im Vordergrund soll schließlich die GUI-Erstellung an sich und nichts anderes stehen) Dennoch hoffe ich, dass dieses Tutorial dem ein oder anderen AutoIt-Nutzer ermutigt, sein eigenes Programm oder gar ein kleines 2D-Spiel zu entwickeln. Wer weiß, vielleicht liest man irgendwann im Forum, dass es einen Ersatz für XP-Antispy, WEB.DE-Smartsurfer oder ein kleines Bildprogramm gibt, weil sich jemand die Mühe machte, sowas auch zu erstellen :) . In diesem Sinne verbleibe ich mit freundlichem Gruß, Manuel