[Tutorial] Sauber Programmieren

  • Tutorial: Sauber Programmieren

    Herzlich willkommen an all jene, die sich in mein Tutorial verirrt haben. ;)
    Kurze Erklärung, worum es hier überhaupt geht:
    Sauber Programmieren heißt für mich, strukturierten & aufgeräumten Code zu erzeugen, was ich euch gerne vermitteln möchte. Dies ist wahrscheinlich insbesondere für Neulinge interessant, die "Veteranen" wissen ja, wie man sowas macht.^^
    Ein Überblick über die Themen:
    - Struktur eines Scriptes
    - Variablen & Funktionsaufrufe
    - Funktionsdeklarierung
    - GUI-Erstellung
    - Extra: Checkliste
    - Kommentare
    - Die Veröffentlichung
    - Nachwort

    So, dann fangen wir mal mit dem ersten Thema an:

    Struktur eines Scriptes

    Ein Script besteht aus mehreren Abschnitten oder Regionen, die man möglichst nicht durcheinander bringen sollte. Diese sind:
    - Includes / Wrapperbefehle
    - AutoIt-Optionen (AutoItSetOption oder Opt)
    - Variablendeklaration
    - Funktionsdeklaration
    - Hauptschleife

    Diese 4 verschiedenen Regionen gilt es nun, richtig anzuordnen. Gewisse Sachen müssen zwangsläufig beachtet werden, andere gehören zu dem "sauberen Programmieren". Selbstverständlich werden wir beides behandeln:
    Als erstes haben wir den Punkt "Includes / Wrapperbefehle". Damit ist praktisch alles gemeint, was mit "#" beginnt. Meistens sind das "#include", "#RequireAdmin" & "#NoTrayIcon" (Alle Befehle sind in der Hilfe nachschlagbar). Diese sollte man an den Anfang der Datei stellen, da danach ja erst das eigentlich AutoIt-Script beginnt.
    Danach folgen die AutoIt-Spezifischen Optionen. Diese können per AutoItSetOption festgelegt werden. Eine Liste der Optionen ist der Hilfe zu entnehmen.
    Dann gibt es die Variablendeklaration, wozu ich hier auch die GUI-Funktionen zähle, denn

    [autoit]


    $hGUI = GUICreate("Test",250,250)

    [/autoit]


    ist nichts anderes als eine Variablenbestimmung, wobei hier $hGUI mit dem Handle der erstellten GUI gefüllt wird. Diese kommen im Normalfall direkt nach den Includes, also an den eigentlichen Anfang des AutoIt-Scriptes. Hier kommen auch solche Sachen wie

    [autoit]


    $sTitle = "Mein Programm!"

    [/autoit]


    hin. Natürlich kommen Variablenzuweisungen, die durch eine Benutzeraktion o.Ä. ausgelöst werden sollen, nicht hierhin. Insbesondere möchte ich hier nochmal auf die Problematik globaler Variablen hinweisen & dazu diesen Beitrag von BugFix zu zeigen: Klick! .
    Als nächstes kommt die Hauptschleife. Diese MUSS nach der Variablendeklaration, bzw. GUI-Erstellung erfolgen, da sonst die GUI nie erstellt wird & die Variablen nie zugewiesen werden. Mit Hauptschleife meine ich soetwas:

    [autoit]


    While 1
    $iMsg = GUIGetMsg()
    Switch $iMsg
    Case $GUI_EVENT_CLOSE
    Exit
    EndSwitch
    WEnd

    [/autoit]


    Ohne diese Schleife würde sich euer Script beenden, da es einfach einmal durchrasseln würde und dann wäre es das gewesen, daher der Name Hauptschleife. Ich persönlich handhabe es so, dass ich alle Routinen, die durch Buttons, Labels etc. ausgelöst werden, daher eigentlich in die Hauptschleife gehören, in Funktionen auslagere, damit ich nicht den Überblick über die Hauptschleife verliere, solche Einzeiler wie Exit oder MsgBox() natürlich ausgenommen. Ein kleines Beispiel:

    [autoit]


    While 1
    $iMsg = GUIGetMsg()
    Switch $iMsg
    Case $GUI_EVENT_CLOSE
    Exit
    Case $Button1
    _Button1Funktion()
    Case $Button2
    _Button2Funktion()
    EndSwitch
    WEnd

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

    Func _Button1Funktion()
    MsgBox(0,"","Button 1 wurde gedrückt!")
    ;...
    EndFunc

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

    Func _Button2Funktion()
    MsgBox(0,"","Button 2 wurde gedrückt!")
    ;...
    EndFunc

    [/autoit]

    ... Wo wir auch schon bei den Funktionsdeklarationen wären. Diese erfolgen normalerweise nach der Hauptschleife, wie ihr im Beispiel oben ( /|\ ) sehen könnt. Näheres zur Funktions(und Variablen-)Deklaration später.
    Behaltet diese oder eure gewählte Struktur (Man kann ja auch z.B. die Funktionen mit den Variablen festlegen) am besten bei jedem eurer Scripts bei. Das erleichtert anderen & euch selber das Lesen eures Codes. Hier nochmal ein kurzer Überblick der Reihenfolge:
    1. Includes & Wrapperbefehle
    2. Variablen-, Konstanten- & GUI-Deklarationen
    3. Hauptschleife
    4. Funktionen

    Weiter zum nächsten Thema!

    Variablen & Funktionsaufrufe


    Die saubere Variablendeklaration ist wichtiger, als man auf den ersten Blick denken mag. Wenn ihr im Moment des Scriptens Variablen wie "$Bla", "$eumel" oder "$mirfälltgeradekeinnameein" benutzt, dann mag euch das nicht ausmachen, jedoch spätestens eine Woche später habt ihr keine Ahnung mehr, was diese Variablen enthalten. Darum ist es wichtig, Namen zu vergeben, an denen man möglichst auf den ersten Blick den Sinn und Zweck einer Variable erkennt. (Zur guten Lesbarkeit empfehle ich euch, eure Variablen, hinsichtlich der Groß und Kleinschreibung, so zu gestalten: $IchBinEineVariable, also jedes Wort mit einem Großbuchstaben zu beginnen). Weiterhin sollte man beim sauberen Programmieren die Liste der Variablenpräfixe beachten:

    Achtung! Mittlerweile scheint es eine neue Liste zu geben, über die ich eben von unserem lieben minx informiert worden bin.
    Das bedeutet jedoch nicht, dass ihr alle eure Skripte umschreiben müsst. ;) Beide "Stile" sind vollkommen okay, nur ist der eine halt aktueller.

    Neue Präfixliste
    Zitat
    • $a<letter> - Array (the following letter describes the data type taken from the rest of the data types below, if it varies then v should be used. A counter as the first element is ignored, so the array returned by StringSplit (with default options) would actually be marked as $as despite the integer in the zeroeth element).
    • $d - Binary data.
    • $h - Handle, usually to a file or window. NB: AutoIt handled controls return IDs, and so use $id instead.
    • $id - An AutoIt control Id.
    • $i - Integer.
    • $b - Boolean.
    • $f - Floating point number.
    • $n - general number with no preference for floating point or integral.
    • $s - String.
    • $v - Variant (unknown/variable type of data) .
    • $p - Pointer. It is assumed that it points to a struct so no further letters are needed. The type of struct being pointed to should be inferrable from the variable name e.g. $pWindowRect can be assumed to be a pointer to a $tagRECT structure.
    • $t - Structure returned from DllStructCreate.
    • $tag - Struct definition string.Structure definitions should conform to the structure guidelines.


    Quelle


    Deutsche Übersetzung:

    • $a<Präfix> - Array, <Präfix> (Optional) bezeichnet den enthaltenen Datentyp
    • $d - Binärdaten
    • $h - Handle
    • $id - Eine AutoIt-ControlID (Rückgabe der GUICtrlCreate-Befehlsreihe)
    • $i - Ganzzahl
    • $b - Bool'scher Wert (True & False)
    • $f - Fließkommazahl
    • $n - Zahl (Egal ob Fließkommazahl oder Ganzzahl)
    • $s - Zeichenkette
    • $v - Variant (Wechselnder oder unbekannter Datentyp)
    • $p - Zeiger
    • $t - Rückgabewert von DllStructCreate
    • $tag - String mit Bildungsvorschrift der DllStruct (Übergabe an DllStructCreate)
    Alte Präfixliste


    Eine kurze deutsche Erläuterung:
    $a<Buchstabe> - Array (Mit dem nächsten Buchstabe wird der Datentyp des Arrayinhaltes angezeigt.
    $b - Binärdaten
    $h - Datei- oder Fenster-Handle (Beispiel: $hGUI = GUICreate("Test",250,250) ).
    $i - Integer, also eine Zahl ohne Nachkommastellen: 1; 100; -50; 123456 etc...
    $f - Boolean, ein booleanischer Wert, sprich entweder "True" oder "False".
    $n - Fließkommazahl, sprich eine Zahl mit einem Komma: 1,5; 10,0006 etc...
    $s - String, d.h. ein Stück Text, zum Beispiel: $sBeispiel = "Ich bin ein Beispiel!"
    $v - Variant. Variant bedeutet, dass der Datentyp, den die Variable enthält, unbekannt oder wechselnd ist.

    Bitte die Datentyperkennungsbuchstaben NICHT groß schreiben!

    Weiterhin ist es wichtig, zu wissen, wann man Variablen deklariert. Solche Zeilen sind ungern gesehen:

    [autoit]


    MsgBox(0, "", "Der Text auf jeder Seite um 1 Stelle gekürzt: " & StringTrimRight(StringTrimLeft(InputBox("", "Dein Text:"), 1), 1))

    [/autoit]


    Zwecks Debugging & Lesbarkeit sollte man so verfahren:

    [autoit]


    $sInput = InputBox("", "Dein Text:")
    $sInputGekuerzt = StringTrimLeft(StringTrimRight($sInput, 1), 1) ;Kann man alternativ auch in 2 Zeilen aufteilen!
    MsgBox(0, "", "Dein Text:" & $sInputGekuerzt)

    [/autoit]


    Ihr wisst bestimmt was ich meine.

    Funktionsdeklaration


    Mit Funktionsdeklaration ist soetwas gemeint:

    [autoit]


    Func MeineFunktion()
    MsgBox(0, "", "Hallo Welt!")
    EndFunc

    [/autoit]


    Wo diese Festlegung erfolgt, wisst ihr ja bereits.^^
    Generell beginnen alle UDF's (User Defined Function) mit einem Unterstrich ("_"), um ebendies zu kennzeichnen. Wichtig ist hier, wie bei den Variablen, übersichtliche Namen zu verwenden; Niemand weiß, was MeineFunktion() macht, ohne sich die Funktion genau anzugucken, und nebenbei wird der User durch den fehlenden Unterstrich verwirrt.
    So ist es besser:

    [autoit]


    Func _MeineMsgBox()
    MsgBox(0,"","Hallo Welt!")
    EndFunc

    [/autoit]


    Eine Funktion sollte so benannt werden, dass der Name möglichst genau beschreibt, was die Funktion macht (Sollte aber nicht zu lang werden^^). Auch besteht die Möglichkeit, Funktionen, die durch eine GUI-Interaktion o.Ä. aufgerufen wird, nach dem Controlhandle zu benennen. Ein Beispiel:

    Script 1
    [autoit]


    While 1
    $iMsg = GUIGetMsg()
    Switch $iMsg
    Case $GUI_EVENT_CLOSE
    Exit
    Case $Button1
    _MeineErsteMsgBox()
    Case $Button2
    _MeineZweiteMsgBox()
    EndSwitch
    WEnd

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

    Func _MeineErsteMsgBox()
    MsgBox(0,"","Button 1 wurde gedrückt!")
    ;...
    EndFunc

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

    Func _MeineZweiteMsgBox()
    MsgBox(0,"","Button 2 wurde gedrückt!")
    ;...
    EndFunc

    [/autoit]
    Script 2
    [autoit]


    While 1
    $iMsg = GUIGetMsg()
    Switch $iMsg
    Case $GUI_EVENT_CLOSE
    Exit
    Case $Button1
    _Button1Funktion()
    Case $Button2
    _Button2Funktion()
    EndSwitch
    WEnd

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

    Func _Button1Funktion()
    MsgBox(0,"","Button 1 wurde gedrückt!")
    ;...
    EndFunc

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

    Func _Button2Funktion()
    MsgBox(0,"","Button 2 wurde gedrückt!")
    ;...
    EndFunc

    [/autoit]


    Ich denke, es ist allen klar, was ich damit meine.
    Funktionen werden außerdem so beendet:

    [autoit]


    Func _MachWas()
    ;... Code ...
    EndFunc ;==>_MachWas

    [/autoit]


    Sprich ein ";==>" gefolgt von dem Funktionsname.
    Auf Funktionsheader gehe ich hier nicht ein, da diese eher zu UDF's gehören, ich mich hier aber auf "normale" Scripte konzentriere.

    GUI-Erstellung


    So viel kann ich garnicht mehr zur GUI-Erstellung sagen, da ich in den vorherigen Themen immer wieder auf diesen Bereich eingegangen bin... Von daher solltet ihr vielleicht dort nochmal gucken.^^
    Eine Sache habe ich aber noch überhaupt nicht angesprochen:
    Die Code-Einrückung.
    Die allgemeine Code-Einrückung kann Tidy für euch übernehmen (Dazu hier jetzt keine Erklärung, folgt vielleicht später), der Bereich GUI erledigt Tidy, meiner Ansicht nach, nicht zufriedenstellend. Ein eingerückter GUI-Code mit Tidy sieht so aus:

    Tidy-Source
    [autoit]


    $Form1 = GUICreate($sTitle, 300, 60)
    GUISetBkColor(0x000000, $sTitle)
    $Rot_Input = GUICtrlCreateInput("0", 0, 0, 50, 20, $ES_NUMBER)
    GUICtrlSetBkColor($Rot_Input, 0xff0000)
    $Gruen_Input = GUICtrlCreateInput("0", 0, 20, 50, 20, $ES_NUMBER)
    GUICtrlSetBkColor($Gruen_Input, 0x00ff00)
    $Blau_Input = GUICtrlCreateInput("0", 0, 40, 50, 20, $ES_NUMBER)
    GUICtrlSetBkColor($Blau_Input, 0x0000ff)
    $Rot_Slider = GUICtrlCreateSlider(50, 0, 190, 20)
    GUICtrlSetBkColor($Rot_Slider, 0xff0000)
    GUICtrlSetLimit($Rot_Slider, 255, 0)
    $Gruen_Slider = GUICtrlCreateSlider(50, 20, 190, 20)
    GUICtrlSetBkColor($Gruen_Slider, 0x00ff00)
    GUICtrlSetLimit($Gruen_Slider, 255, 0)
    $Blau_Slider = GUICtrlCreateSlider(50, 40, 190, 20)
    GUICtrlSetBkColor($Blau_Slider, 0x0000ff)
    GUICtrlSetLimit($Blau_Slider, 255, 0)
    $Farbe_Label = GUICtrlCreateButton("OK", 240, 0, 60, 60)
    GUICtrlSetFont($Farbe_Label, 14)
    GUISetState(@SW_SHOW)

    [/autoit]


    Ich habe mir jedoch im Laufe der Zeit folgende Variante angewöhnt:

    Einrückung #1
    [autoit]


    $Form1 = GUICreate($sTitle, 300, 60)
    GUISetBkColor(0x000000, $sTitle)
    $Rot_Input = GUICtrlCreateInput("0", 0, 0, 50, 20, $ES_NUMBER)
    GUICtrlSetBkColor($Rot_Input, 0xff0000)
    $Gruen_Input = GUICtrlCreateInput("0", 0, 20, 50, 20, $ES_NUMBER)
    GUICtrlSetBkColor($Gruen_Input, 0x00ff00)
    $Blau_Input = GUICtrlCreateInput("0", 0, 40, 50, 20, $ES_NUMBER)
    GUICtrlSetBkColor($Blau_Input, 0x0000ff)
    $Rot_Slider = GUICtrlCreateSlider(50, 0, 190, 20)
    GUICtrlSetBkColor($Rot_Slider, 0xff0000)
    GUICtrlSetLimit($Rot_Slider, 255, 0)
    $Gruen_Slider = GUICtrlCreateSlider(50, 20, 190, 20)
    GUICtrlSetBkColor($Gruen_Slider, 0x00ff00)
    GUICtrlSetLimit($Gruen_Slider, 255, 0)
    $Blau_Slider = GUICtrlCreateSlider(50, 40, 190, 20)
    GUICtrlSetBkColor($Blau_Slider, 0x0000ff)
    GUICtrlSetLimit($Blau_Slider, 255, 0)
    $Farbe_Label = GUICtrlCreateButton("OK", 240, 0, 60, 60)
    GUICtrlSetFont($Farbe_Label, 14)
    GUISetState(@SW_SHOW)

    [/autoit]


    Meiner persönliches Ansicht nach macht dieses Verfahren das Lesen der GUI-Sektion um einiges leichter.
    Edit: Nach einigen Einwürfen gegen dieses Einrückungsverfahren, halte ich diese Variante für einen praktikablen Kompromiss. Anstatt der Tab-Einrückung wird einfach eine Space-Einrückung verwendet.

    Einrückung #2
    [autoit]


    $Form1 = GUICreate($sTitle, 300, 60)
    GUISetBkColor(0x000000, $sTitle)
    $Rot_Input = GUICtrlCreateInput("0", 0, 0, 50, 20, $ES_NUMBER)
    GUICtrlSetBkColor($Rot_Input, 0xff0000)
    $Gruen_Input = GUICtrlCreateInput("0", 0, 20, 50, 20, $ES_NUMBER)
    GUICtrlSetBkColor($Gruen_Input, 0x00ff00)
    $Blau_Input = GUICtrlCreateInput("0", 0, 40, 50, 20, $ES_NUMBER)
    GUICtrlSetBkColor($Blau_Input, 0x0000ff)
    $Rot_Slider = GUICtrlCreateSlider(50, 0, 190, 20)
    GUICtrlSetBkColor($Rot_Slider, 0xff0000)
    GUICtrlSetLimit($Rot_Slider, 255, 0)
    $Gruen_Slider = GUICtrlCreateSlider(50, 20, 190, 20)
    GUICtrlSetBkColor($Gruen_Slider, 0x00ff00)
    GUICtrlSetLimit($Gruen_Slider, 255, 0)
    $Blau_Slider = GUICtrlCreateSlider(50, 40, 190, 20)
    GUICtrlSetBkColor($Blau_Slider, 0x0000ff)
    GUICtrlSetLimit($Blau_Slider, 255, 0)
    $Farbe_Label = GUICtrlCreateButton("OK", 240, 0, 60, 60)
    GUICtrlSetFont($Farbe_Label, 14)
    GUISetState(@SW_SHOW)

    [/autoit]

    Extra: Checkliste


    Nun ist es soweit: Ihr habt euer Script fertig & wollt es nun der Community auf AutoIt.de präsentieren. Jedoch solltet ihr, bevor ihr dies tut, nocheinmal euer Script in Sachen Übersichtlichkeit & Struktur überprüfen. Hier eine kleine Checkliste:

    Code
    [ ] - Richtige allgemeine Struktur des Codes (Wrapper, Variablen, Schleife, Funktionen)
    [ ] - Vernünftige Variablennamen
    [ ] - Variablentyp-Angabe
    [ ] - Vernünftige Variablendeklarationen
    [ ] - Vernünftige Funktionsnamen
    [ ] - Unterstrich vor den Funktionsnamen
    [ ] - Hauptschleife sauber, alles in Funktionen ausgelagert
    [ ] - Code-Einrückung (Tidy)


    Ich möchte an dieser Stelle nocheinmal darauf hinweisen, dass die wenigsten dieser Punkte eine direkte Wirkung auf die Funktion eures Scriptes haben. Strukturierter Code ist die eindeutig bessere Wahl, jedoch muss jeder selber entscheiden, ob er seinen Quelltext so gestaltet.

    Wenn ihr jedenfalls all diese Punkte beachtet, wird euch gewiss keiner anmeckern, dass euer Script nicht ordentlich sei.^^
    Im Allgemeinen ist es übrigens eine gute Idee, in eurem Script auf Rechtschreibung zu achten. ;)

    Nachdem das Thema „Kommentare“ hier mehrmals angesprochen wurde, habe ich mal einen kleinen Textabschnitt dazu verfasst:

    Kommentare


    Kommentare dienen dazu, euren Quelltext verständlicher zu machen. Mit ihnen können Fremde euren Source praktisch ohne Vorwissen verstehen, vielleicht könnte sogar jemand ohne die geringsten AutoIt-Kenntnisse euren Code nachvollziehen. Man kommentiert vor allem den aktuellen Vorgang im Script. So kann man zum Beispiel...

    ... einen Befehl kommentieren:

    [autoit]


    ;...
    $hGUI = GUICreate(„Test“,250,250) ;GUI wird erstellt
    ;...

    [/autoit]


    … eine Funktion beschreiben:

    [autoit]


    ;...
    Func _MinimizeWindow() ;Minimiert die GUI
    GUISetState(@SW_MINIMIZE,$hGUI)
    EndFunc ;==>_MinimizeWindow
    ;...

    [/autoit]


    … den Inhalt einer Variable beschreiben:

    [autoit]


    ;...
    $iCounter = 0 ;Setzt den Counter für die Schleife auf 0.
    ;...

    [/autoit]


    Bei dem Inhalt einer Variable möchte ich euch noch ein LUA-Script von einem unserer Mods zeigen, was ich persönlich sehr nützlich finde: Klick!
    Danke, BugFix! ;)

    Weiterhin zählt der Standardheader einer Datei auch als Kommentar. Schauen wir ihn uns kurz an:

    [autoit]


    #cs ----------------------------------------------------------------------------

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

    AutoIt Version: 3.3.8.1
    Author: myName

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

    Script Function:
    Template AutoIt script.

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

    #ce ----------------------------------------------------------------------------

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

    ; Script Start - Add your code below here

    [/autoit]


    Ich denke, den meisten dürfte der Inhalt klar sein. Trotzdem nochmal:
    -AutoIt Version: Eure für das Script verwendete AutoIt-Version. Wenn ihr zum Beispiel ein Script mit der Beta geschrieben habt, was unter der Stable nicht läuft, kann das ziemlich nützlich sein.
    -Author: Das seid ihr. Hier kommt dein Name oder ein Pseudonym hin, alternativ auch beides: „Not_a_DAU (Max Mustermann)“ oder „Max Mustermann (Not_a_DAU)“. Sofern vorhanden, könnt ihr hier auch noch die URL zu eurer Website oder eure e-Mail hinterlegen.
    -Script Function: Beschreibt kurz, wozu euer Script da ist. Es wäre gut, wenn ihr hier (Wie eigentlich überall) auf korrekte Rechtschreibung und Zeichensetzung achtet; das kommt immer besser rüber als irgendein Möchtegerndeutsch-Sprachsalat.

    Im allgemeinen kann man die Kommentar-Funktion dazu benutzen, um ganze Befehlszeilen "auszukommentieren", sodass sie nicht mehr interpretiert werden (z.B. eine MsgBox zum Debugging etc..).
    Es gibt 2 Möglichkeiten:
    - Um eine einzelne Zeile auszukommentieren, reicht es, ein Semikolon (";") davor zu setzen.
    - Um einen ganzen Codeblock auszukommentieren, kann man an den Anfang des Blockes "#cs" oder "#comments-start" setzen, und an das Ende "#ce" oder "#comments-end".
    Noch einfacher geht es, indem ihr die betreffenden Zeilen in SciTE markiert und Strg + Q drückt (Oder die Minus-Taste auf dem Numpad). Entfernen könnt ihr die Kommentarzeichen ebenfalls mit Strg + Q.

    Ich denke, das wars so weit zu Kommentaren. Wenn noch jemand einen Aspekt vermisst, bitte bescheid sagen.

    Die Veröffentlichung

    So, der harte, steinige Weg zur Fertigstellung eures sauber geskripteten Programmes ist zu Ende.
    Nun, was fehlt noch?
    Ja, genau! Ihr wollt nun euer Skript mit dem Forum (z.B.) teilen.
    Dazu gehört aber auch eine ordentliche Präsentation!

    Als Beispiel nehmen wir mal ein Thread von unserm lieben Mod BugFix: IntelliSenseBox

    Spoiler anzeigen


    Als StandardControl haben wir ja mit der ComboBox die Möglichkeit eine eingabesensitive Auswahl zu ermöglichen.
    Ich habe hier mal ein Beispiel erstellt, wie man diese Funktionalität auch für z.B. Input-Ctrl erreichen kann.
    Gründe dafür:
    - ich finde es optisch nicht sehr ansprechend, wenn die Schaltfläche der ComboBox die GUI 'verschandelt'
    - ich habe hiermit die Möglichkeit eigene Auswahllisten auch für Fremdanwendungen (so sie denn Standard Windows Controls verwenden) zu nutzen

    Funktionsweise:
    Wird in das Inputfeld ein Buchstabe eingegeben, der auch als Anfangsbuchstabe in der Liste hinterlegt ist, popt das Auswahlfenster auf.
    Der Focus bleibt aber beim Inputfeld.
    Ist in der Liste kein Eintrag mit diesem Buchstaben, wird sie auch nicht eingeblendet.
    Es wird mit jedem weiteren Buchstaben auf Übereinstimmung geprüft und entsprechend der erste Eintrag markiert, auf den die bisherige Eingabe zutrifft.
    Mit PFEIL AUF / PFEIL AB kann in der Liste die Auswahl verschoben werden.
    Mit ENTER wird der momentan markierte Eintrag aus der Liste in das Input übernommen.
    Mit ESC kann die Liste ohne Übernahme gechlossen werden.


    Edit 08.03.09:
    Habe das Skript nochmal etwas bearbeitet. Alle bisher im Thread besprochenen Änderungen/Ergänzungen sind enthalten.
    Es ist jetzt allgemein gehalten, sodass es für Input- und ComboBox-Ctrl gleichermaßen verwendet werden kann. Es brauchen auch keine Anpassungen in den Funktionen für die Control-ID's erfolgen.
    Es muß zur Anwendung nur noch folgendes getan werden:
    - Einmalig bei der Erstellung eine Zuweisung auf den allgemeinen Namen ($SenseGui u. $SenseCtrl)
    - Befüllen des DatenArray mit den Auswahldaten

    Edit zum Edit: $nNotifyCode für ComboBox fehlte noch :S - jetzt komplett

    Diese Präsentation hat eigentlich alles, was benötigt wird. Das wäre dann (im Groben):

    • Einleitungstext
      Hier wird kurz beschrieben, worum es geht, und - wie BugFix - auch, wieso man das Skript geschrieben hat.
      Also Informationen, die zwar interessant sind, aber nicht unbedingt benötigt werden - Eine Einleitung halt. ;)
    • Allgemeine Informationen
      Hier solltet ihr kurz sagen, wie euer Skript überhaupt funktioniert. Das bedeutet: Bedienung, Umstände bei der Benutzung, Einsatzzweck... Alle relevanten Information halt.
      Das kann (Bzw. sollte) in Form eines schönen Textes umgesetzt werden.^^
      Diesen Part kann man auch noch weiter ausgliedern.
    • Changelog
      Ein größeres Programm, was Updates bekommt, sollte stehts ein Changelog haben.
      Wer nicht weiß, was ein Changelog ist: Ein Text(dokument), welches alle Änderungen, das Änderungsdatum plus dazugehörige Versionsnummern vom Programm enthält.
      Es gibt 2 Möglichkeiten, das zu handeln. Einmal, wie BugFix & ich, indem man den Changelog im ersten Post verewigt, und bei einer neuen Programmversion einen neuen Post schreibt, in welchem darauf hingewiesen wird (Siehe BugFix-Thread Post 8 ).
      Die andere Möglichkeit ist, die jeweiligen Changelog-Informationen in einzelne Posts zu schreiben, und dann jeweils nur diese im Startpost zu verlinken. Ich empfehle aber eher ersteres.
      Edit:
      minx hat mich darauf hingewiesen, dass es noch eine dritte Möglichkeit gibt, die wir wohl alle kennen: Eine CHANGELOG, README & TODO-Datei.
      Man kann die Skriptdatei zippen und eben jene Dateien mit in den Ordner legen. Bei einer neuen Version kann man dann einen Informationspost erstellen und einfach die ZIP im Startpost anhängen.^^

      Weiterhin kann man dieses Changelog bei großen Projekten noch weiter aufgliedern, zum Beispiel in "Neue Funktionen", "Gefixte Bugs" & "Neue Bugs".^^
      Um also nochmal zusammenzufassen: Datum, Version & Information!

    • Groß-, Klein- & Rechtschreibung
      Es ist natürlich wichtig, dass ihr auf möglichst tadellose Orthografie achtet.
      Ein Programm, was "Windos Fenstermeneger" heißt, macht nicht allzu viel her... :whistling:
    • Textformatierung via BBCode
      Mit BBCode seinen Text zu formatieren, ist immer gut - Solange man nicht übertreibt. ;)
      Man sollte die wichtigsten Sachen hervorheben. Ich habe mal ein Beispiel geschrieben:

      Spoiler anzeigen

      <Programmname>


      <Einleitung>
      Funktionsweise
      <Funktionsweise>

      Changelog
      • Version 0.9 (09.01.2013)

        • Neue Funktionen:

          • - Neue Funktion 1
          • - Neue Funktion 2
        • Gefixte Bugs:

          • - Fenster nun schließbar
          • - Kein Array-Fehler nach längerer Laufzeit mehr
        • Neue Bugs:

          • - Fehler in Funktion 2
      • Version 1.0 (11.01.2013)

        • Neue Funktionen:

          • - Neue Funktion 3
        • Gefixte Bugs:

          • - Bug in Funktion 1 gefixt
        • Neue Bugs:

          • - Keine!


      Man kann außerdem auch inhaltlich wichtige Sachen in Sätzen per BBCode hervorheben (Wie ich das gerade getan habe). ;)

    Generell solltet ihr darauf achten, dass euer Post Struktur hat, und nicht nur wild durcheinander gewürfelt ist. Bei inhaltlichen Schnitten mal eben einen Absatz zu setzen, tut nun wirklich nicht weh. ;)

    Ihr solltet euch auf jeden Fall Zeit für eure Präsentation nehmen, denn ihre Qualität wird einen Großteil der Entscheidung, euer Programm anzuschauen, bei den anderen Usern ausmachen!


    Nachwort


    Nun, nach 1 - 2 Stunden Arbeit ist mein kleines Tutorial (Was größer wurde, als ich dachte) fertig. Ich hoffe, es hilft ein paar Leuten, sauberes Programmieren zu lernen.
    Eventuell kommt auch noch ein Extra zum Thema Header hinzu, sprich Funktionsheader & Scriptheader, mal sehen. ;)
    Viel Spaß mit dem Zeug,
    lg chess

    PS: Die Codeeinrückung und Textformatierung hier im Thread kommt noch. :P
    Müsste eigentlich soweit erledigt sein. Wenn jemandem ein Fehler auffällt, egal ob Design-, Rechtschreib-, Logik- oder Script-Fehler, dann bitte bescheid sagen!
    Ach ja, Lob & Kritik wären auch ganz nett. ;)

    Edit (04.06.2012): Diverse Schönheitsfehler ausgebessert. :rolleyes:
    Edit (12.06.2012): $nMsg zu $iMsg korrigiert & Präfix-Liste erweitert.
    Edit (01.12.2012): Numpad Minus als Alternative zu Strg+Q eingetragen (Danke an RechterWinkel!).
    Edit (02.12.2012): Neue Präfix-Liste eingestellt (Danke an minx!).
    Edit (28.12.2012): Opt/AutoItSetOption zur Struktur zwischen Präprozessoranweisungen und Variablendeklaration hinzugefügt (Danke an FKFK!)´
    Edit (11.01.2013): Neues Kapitel "Die Veröffentlichung" hinzugefügt (Danke an BugFix für die Erlaubnis, seinen Thread als Beispiel benutzen zu dürfen!)
    Edit (20.03.2014): Ein paar kleine Schönheitsfehler beseitigt. Wieder. :whistling:

  • Hi, da hast du dir ja viel Mühe gemacht! Großes Lob!
    Wo ich mir das so durchlese: Ich glaube, ich missachte gefühlt 90% der von dir aufgeführten Regeln :rolleyes:. Ich werde mich als mal bemühen, in Zukunft nicht mehr so dreckig zu programmieren :).

    Allerdings habe ich einen Fehler gefunden:

    [autoit]

    $sInput = InputBox("","Dein Text:")
    $sInputGekürzt = StringTrimLeft(StringTrimRight($sInput,1),1) ;Kann man alternativ auch in 2 Zeilen aufteilen!
    MsgBox(0,"","Dein Text:" & $sInputGekürzt)
    $Button_Exit("Wenn du dieses Label nicht putzig findest, kommst du mit mir hier weg!",100,100)

    [/autoit]


    Das wird nicht laufen. In Zeile 2 verwendest du einen Umlaut im Variablennamen.

    Ansonsten: Sehr schönes Tutorial!

  • Nette Übersicht, aber mal ehrlich wär hällt sich schon privat an Programmierparadigmen ;).

    Das mit der Geschwindigkeit hatten wir mal in der SB...
    $i += 1 ist ca. 2 ms schneller als $i = $i + 1, ist mir da schon aufgefallen.

    Meines wissens nach ging diese Sache komplett unentschieden aus, da bei dem eine das eine und beim anderen das andere schneller war ;). Deine Doktorarbeit dazu wird übrigens noch erwartet :P.

    Andy hat mir ein Schnitzel gebacken aber da war ein Raupi drauf und bevor Oscar das Bugfixen konnte kam Alina und gab mir ein AspirinJunkie.

  • Ja die Ergebnisse waren sehr unterschiedlich.
    Bei mir war "$i+=1" auch (ca. um Faktor 4) schneller als "$i = $i+1"!
    Bei anderen war es umgekehrt?
    Wobei man eigentlich überall lesen kann, dass "$i+=1" schneller sein müsste. Imho auch logisch, da die Variable nur einmal ausgelesen werden muss.

    Zum Thema: Ich vermisse bei den Variablen die unterscheidung zwischen "Local" und "Global".

  • Jap, bei mir ist es umgekehrt :D
    die klassische Variante ist iwie schneller (2.3x)?!?

    $sInputGekürzt geht nicht!! Keine Umlaute in Variablenbezeichnungen und Funktionen möglich!
    Sonst finde ich dein Tut echt gut; ist so ziemlich das erste hier welches sich auf die Programmstruktur und -Leserlichkeit bezieht! Solltest du aber noch erweitern - da fehlen noch viele Punkte.

    Grüsse!

  • Techmix
    Ja, da fehlen viele Punkte, werde ich mich noch ransetzen, spontan fallen mir aber nur Kommentare & Geschwindigkeit ein...
    Das mit dem $sInputGekürzt ist mir jetzt ein bisschen peinlich... Hab das meiste in Wordpad getippt, sonst wär mir das beim Syntax-Highlighting aufgefallen.
    Danke, wird korrigiert!;)

    nuts
    Was die Unterscheidung von Global & Local angeht...
    Ich bin absichtlich um so ein Thema herumgeschifft, da es in diesem Tutorial ja nur um den Programmierstil geht, nicht um das Programmieren an sich, wenn du weißt, was ich meine. ;)

    chip
    Achja, meine Doktorarbeit. ;)
    Ich werde das in der nächsten Zeit nochmal ausgiebig testen, auf 5+ verschiedenen PC's mit den gleichen Scripten.
    Mal sehen was da raus kommt, die Ergebnisse sind dann entweder hier oder in einem eigenen Thread zu finden.

    Danke an alle für das Review!
    lg chess

  • Also ich finde das Tutorial sehr gelungen, und obwohl man immer etwas verbessern oder hinzufügen kann, sorgt es hoffentlich jetzt schon dafür, dass die Skripte, die es noch nicht sind, lesbarer werden.

    MfG, James C.

    PS: Hier noch etwas für deine Doktorarbeit:

    Spoiler anzeigen
    [autoit]

    Local $i, $j, $timer, $a = 0, $b = 0
    For $i = 1 To 1000 Step 1
    $j = 1
    $timer = TimerInit()
    $j = $j + 1
    $a += TimerDiff($timer)
    If ($i > 1) Then $a /= 2
    $j = 1
    $timer = TimerInit()
    $j += 1
    $b += TimerDiff($timer)
    If ($i > 1) Then $b /= 2
    Next
    ConsoleWrite('i = i + 1 ' & $a & @LF & 'i += 1 ' & $b & @LF)

    [/autoit]
    Code
    i = i + 1  0.00332291030910433
    i += 1     0.00288285947793538
  • Wenn du es so machst holst du dir die Ungenauigkeit der Timerfunktion mit herein.
    Stabiler wären die Messergebnisse wenn man es stattdessen so misst:

    Spoiler anzeigen
    [autoit]

    Global Const $N = 10e6
    Global $x = 0, $t, $i

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

    For $i = 1 To $N
    $x += TimerDiff(TimerInit())
    Next
    ConsoleWrite(StringFormat("%16s %10.5fms\n", "Timerauflösung:", $x/$N))

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

    $x = 0
    $t = TimerInit()
    For $i = 1 To $N
    $x = $x + 1
    Next
    $t = TimerDiff($t)
    ConsoleWrite(StringFormat("%16s %10.5fms\n", "$x = $x + 1:", $t/$N))

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

    $x = 0
    $t = TimerInit()
    For $i = 1 To $N
    $x += 1
    Next
    $t = TimerDiff($t)
    ConsoleWrite(StringFormat("%16s %10.5fms\n", "$x += 1:", $t/$N))

    [/autoit]
    • Offizieller Beitrag

    Die Benennung der Variablennamen kann ich so nicht unterstützen, da ein guter Name den Typ bereits deutlich machen kann, z.B. wird die Variable $kosten wohl ein Integer/Float sein, und die ganzen zusätzliche Zeichen machen den Code auch nicht leichter lesbar.


    $kosten ist aber nur in deinem Script und nur für dich eindeutig.
    $iKosten ist schon beim überfliegen des Scriptes für mich besser zu erkenen als ein irre langer Varnamen. ;)
    Und zum Thema lesbar: Wenn sich jemand an die Namensvorgabe hällt, ist das Script um Längen besser zu lesen.

  • nuts
    Was die Unterscheidung von Global & Local angeht...
    Ich bin absichtlich um so ein Thema herumgeschifft, da es in diesem Tutorial ja nur um den Programmierstil geht, nicht um das Programmieren an sich, wenn du weißt, was ich meine. ;)


    Saubere Deklaration der Variablen hat für mich schon was mit Programmierstil zu tun.

  • Außerdem entspricht das Script dann schon den UDF-Standards.
    Ich persönlich neige auch dazu, eigene solcher Variablenpräfixe zu verwenden, welche ich dann aber am Anfang des Scriptes erkläre.
    Beispiel: x steht für Hex. ;)

    lg chess

    Edit:
    Natürlich hat das was mit dem Programmierstil zutun, gewisserweise.
    Aber mein Tutorial bezieht sich sozusagen auf das Äußere. Global & Local haben was mit der Funktion des Scriptes zutun, der Rest ist einfach nur, damit der Code "sauber" ist.
    Außerdem gibt es bestimmt schon genug Tut's zu Global & Local. ;)

    lg chess

  • Hi,
    ich nehm den Startpost einfach mal als Anlaß, dass dieser Thread die Fundgrube für Tips/Tricks und Goodies wird :thumbup:

    Was noch garnicht beachtet/beschrieben wurde, ist die essenzielle Verwendung von KOMMENTAREN!
    Durch 10 Zeilen Kommentare hat man das Programm und dessen Ablauf besser beschrieben als durch noch so feine Variablennamen 8)
    Kommentare werden durch das Semikolon vom Code getrennt, automatisch ausrichten lassen sie sich durch Verwendung von AlignComment

    Über absolute Must-have´s wie OrganizeIncludes (wieso gibts das eigentlich nicht als in Scite integrierte Funktion wie Tidy? ) und SendToPastebin braucht man nicht weiter zu reden, ohne ist AutoIt nur "halb"^^

  • Zitat von Chesstiger


    Techmix
    Ja, da fehlen viele Punkte, werde ich mich noch ransetzen, spontan fallen mir aber nur Kommentare & Geschwindigkeit ein...
    Das mit dem $sInputGekürzt ist mir jetzt ein bisschen peinlich... Hab das meiste in Wordpad getippt, sonst wär mir das beim Syntax-Highlighting aufgefallen.
    Danke, wird korrigiert!

    Aber trotzdem danke, ich bin schon was am tippen. :P

    lg chess

  • Gutes Tutorial.
    Vielen Dank.

    Das mit der Variablenbenennung habe ich mir auch so wie im Tutorial beschrieben (zu 98% auch eingehalten) angewöhnt.

    Nur habe ich noch einen zusätzlichen Buchstaben. Ich verwende noch $p...... als Prefix für Pfade, da ich viele Pfade speichern muss und sie von anderen Strings unterscheiden möchte!

    Gruß
    Veronesi

  • Nichts dagegen :)
    Obwohl ich mir nicht sicher bin, ob $p.... nicht für Pointer verwendet werden sollte?
    Konnte mich da nie entscheiden, was ich für Pointer nehme. ($ptr....) ?