Konzepte und Konventionen

Dieses Dokument behandelt einige allgemeine Konzepte und Konventionen, die von AutoHotkey verwendet werden, wobei der Schwerpunkt eher auf Erklärungen als auf Code liegt. Es wird nicht vorausgesetzt, dass der Leser Vorkenntnisse in Scripting oder Programmierung hat, aber er sollte offen für neue technische Begriffe sein.

Genauere Informationen zur Syntax finden Sie unter Skriptsprache.

Inhaltsverzeichnis

Werte

Ein Wert repräsentiert eine einzelne Information innerhalb eines Programms. Zum Beispiel wäre das der Name einer zu sendenden Taste oder eines zu startenden Programms, die Anzahl der Tastendrücke, der Titel eines zu aktivierenden Fensters, oder was auch immer innerhalb des Programms oder Skripts eine Bedeutung hat.

AutoHotkey unterstützt folgende Typen von Werten:

Einige andere verwandte Konzepte:

Zeichenketten (Strings)

Eine Zeichenkette ist einfach nur Text. Jede Zeichenkette ist eigentlich eine Sequenz, Folge oder Kette von Zeichen. Sie kann aber auch als eine einzelne Entität betrachtet werden. Die Länge einer Zeichenkette entspricht der Anzahl der Zeichen in der Sequenz, während die Position eines Zeichens innerhalb der Zeichenkette lediglich die fortlaufende Nummer dieses Zeichens ist. Gemäß der Konvention von AutoHotkey befindet sich das erste Zeichen auf Position 1.

Numerische Zeichenketten: Eine Kette von Zahlen (oder von anderen unterstützten Zahlenformaten) wird automatisch als Zahl interpretiert, wenn eine mathematische Operation oder ein Vergleich dies erfordert. In AutoHotkey v1 werden Vergleiche numerisch durchgeführt, wenn beide Werte rein numerisch oder numerische Zeichenketten sind. Eine in Anführungszeichen gesetzte Zeichenkette (oder das Ergebnis einer Verkettung mit einer in Anführungszeichen gesetzten Zeichenkette) wird allerdings nie als numerisch gewertet, wenn sie direkt in einem Ausdruck verwendet wird.

Wie literaler (direkt geschriebener) Text in einem Skript geschrieben werden sollte, hängt vom Kontext ab. Weitere Informationen finden Sie unter Legacy-Syntax und Zeichenketten (in Ausdrücken).

Eine genauere Erklärung der Funktionsweise von Zeichenketten finden Sie unter Zeichenkettenkodierung.

Zahlen

AutoHotkey unterstützt folgende Zahlenformate:

Hexadezimalzahlen müssen mit dem 0x- oder 0X-Präfix beginnen, sofern in der Dokumentation nichts anderes angegeben ist. Dieses Präfix muss nach einem Vorzeichen wie + oder -, falls vorhanden, und vor führenden Nullen stehen. Zum Beispiel ist 0x001 gültig, aber nicht 000x1.

Zahlen, die mit einem Dezimalpunkt geschrieben werden, gelten immer als Floating-Point-Zahlen, auch wenn die Dezimalstelle eine Null ist. Zum Beispiel sind 42 und 42.0 in der Regel gleich, aber nicht immer. Die wissenschaftliche Schreibweise wird ebenfalls erkannt, aber nur, wenn ein Dezimalpunkt vorhanden ist (z.B. 1.0e4 und -2.1E-4).

Das Dezimaltrennzeichen ist immer ein Punkt, auch wenn in den Ländereinstellungen des Benutzers ein Komma angegeben ist.

Wenn eine Zahl in eine Zeichenkette umgewandelt wird, wird sie entsprechend dem aktuellen Integer- oder Float-Format formatiert. Obwohl der SetFormat-Befehl verwendet werden kann, um das aktuelle Format zu ändern, sollte besser die Format-Funktion zum Formatieren einer Zeichenkette verwendet werden. Floating-Point-Zahlen können auch mit der Round-Funktion formatiert werden.

Details über den Bereich und die Genauigkeit von numerischen Werten finden Sie unter Reine Zahlen.

Boolesche Werte

Ein boolescher Wert kann entweder True (wahr) oder False (falsch) sein. Boolesche Werte werden verwendet, um etwas wiederzugeben, das exakt zwei mögliche Zustände hat, wie z.B. die Wahrheit eines Ausdrucks. Der Ausdruck (x <= y) ist z.B. True, wenn x kleiner gleich y ist. Ein boolescher Wert könnte auch Yes oder No, On oder Off, Down oder Up (z.B. bei GetKeyState) und so weiter repräsentieren.

AutoHotkey hat keinen spezifischen booleschen Wertetyp und verwendet daher den Integerwert 0 für False und 1 für True. In Fällen, wo der Wert entweder True oder False sein muss, wird eine leere Zeichenkette oder 0 als False und alle anderen Werte als True angesehen. (Objekte werden immer als True angesehen.)

Die Wörter True und False sind interne Variablen, die 1 bzw. 0 enthalten. Diese können verwendet werden, um die Lesbarkeit eines Skripts zu verbessern.

Nichts

AutoHotkey hat keinen Wert, der eindeutig nichts, null, nil oder undefined repräsentiert, wie es in anderen Sprachen der Fall ist. Stattdessen hat oft eine leere Zeichenkette (eine Zeichenkette mit der Länge 0) diese Bedeutung.

Wenn eine Variable oder ein Parameter als "leer" bezeichnet wird, ist in der Regel eine leere Zeichenkette (eine Zeichenkette mit der Länge 0) gemeint.

Objekte

Grundsätzlich können Objekte auf zwei verschiedene Arten betrachtet werden:

Die richtige Verwendung von Objekten (und insbesondere Klassen) kann zu modularem und wiederverwendbarem Code führen. Modularer Code ist in der Regel leichter zu testen, zu verstehen und zu pflegen. So kann z.B. ein Abschnitt des Codes verbessert oder geändert werden, ohne dass die Details anderer Abschnitte bekannt sein müssen und ohne dass entsprechende Änderungen an diesen Abschnitten vorgenommen werden müssen. Wiederverwendbarer Code spart Zeit, da das Schreiben und Testen von Code für gleiche oder ähnliche Aufgaben entfällt.

Beim Zuweisen eines Objektes an eine Variable, wie in meinObj := {}, wird nicht das Objekt selbst hinterlegt, sondern eine Referenz zu diesem Objekt. Kopiert man diese Variable, wie in deinObj := meinObj, wird eine neue Referenz zum selben Objekt erstellt. Eine Änderung wie meinObj.ans := 42 würde sich sowohl in meinObj.ans als auch in deinObj.ans widerspiegeln, da beide auf dasselbe Objekt verweisen. meinObj := Object() wirkt sich jedoch nur auf die meinObj-Variable aus, nicht auf die deinObj-Variable, die immer noch auf das ursprüngliche Objekt verweist.

Objektorientierte Schnittstelle

Dieser Abschnitt baut auf folgenden Konzepten auf, die in späteren Abschnitten behandelt werden: Variablen, Funktionen

Objekte arbeiten nach dem Prinzip der Meldungsübermittlung. Sie wissen nicht, wo sich der Code oder die Variablen eines Objekts tatsächlich befinden, also müssen Sie eine Meldung an das Objekt übergeben, wie z.B. "gib mir foo" oder "gehe zu bar", und sich darauf verlassen, dass das Objekt auf die Meldung reagiert. Objekte in AutoHotkey unterstützen die folgenden grundlegenden Meldungen:

Jede Meldung kann optional einen oder mehrere Parameter enthalten (und bei Set den Wert). Normalerweise gibt es mindestens einen Parameter. Dieser Parameter wird als Name einer Eigenschaft oder Methode, als Schlüssel oder als Array-Index interpretiert, je nachdem, welches Objekt vorliegt und wie man es verwendet. Die Parameter einer Meldung können auf drei verschiedene Weisen angegeben werden: .Name, [Params] und (Params), wobei Name ein direkt geschriebener Name oder Identifikator, und Parameter eine Liste von Parametern (als Teilausdrücke) ist, die leer sein kann ([] oder ()).

Bei Get und Set können .Name und [Parameter] synonym verwendet oder kombiniert werden:

meinObj[Param1, Param2, ..., ParamN]
meinObj.Name
meinObj.Name[Param2, ..., ParamN]

Bei Call können .Name und [Parameter] synonym verwendet werden, immer gefolgt von (Parameter):

meinObj.Name(Param2, ..., ParamN)
meinObj[Param1](Param2, ..., ParamN)

Beachten Sie, dass Name, falls vorhanden, zum ersten Parameter wird. meinObj.Name ist äquivalent zu meinObj["Name"], während meinObj.123 äquivalent zu meinObj[123] ist. Dies gilt für jeden Objekttyp, daher ist es jederzeit möglich, den Namen einer Eigenschaft oder Methode während der Skriptausführung zu ermitteln, anstatt ihn manuell in das Skript zu schreiben.

Obwohl Name oder Param1 als erster Parameter gelten, ist zu bedenken, dass es sich dabei nur um Meldungen handelt und es dem Objekt freisteht, wie es damit umgeht. In einem Methodenaufruf wie dem oben gezeigten verwendet das Objekt normalerweise Name oder Param1, um zu identifizieren, welche Methode aufgerufen werden soll, und Param2 und so weiter, um sie an die Methode zu übergeben. Somit wird Param2 der erste offensichtliche Parameter der Methode.

Grundsätzlich hat Set die gleiche Bedeutung wie eine Zuweisung und verwendet daher den gleichen Operator:

meinObj[Param1, Param2, ..., ParamN] := Wert
meinObj.Name := Wert
meinObj.Name[Param2, ..., ParamN] := Wert

Derzeit gibt es für Set auch eine "hybride" Syntax, auf die man aber besser verzichten sollte:

meinObj.Name(Param2, ..., ParamN) := Wert

Technisch gesehen wird der Wert als letzter Parameter der Set-Nachricht übergeben; dieses Detail ist jedoch für Skriptautoren fast nie relevant. Grundsätzlich kann man sich das so vorstellen, dass "der Wert zugewiesen wird".

Variablen

Mithilfe einer Variable können Sie einen Namen als Platzhalter für einen Wert verwenden. Sie können diesen Wert jederzeit während der Skriptausführung ändern. Ein Hotkey könnte z.B. eine Variable press_count verwenden, um zu zählen, wie oft er gedrückt wurde, und jedes Mal eine andere Taste senden, wenn press_count ein Vielfaches von 3 ist (jeder dritte Tastendruck). Eine Variable, der nur einmal ein Wert zugewiesen wird, kann ebenfalls nützlich sein. Zum Beispiel können Sie die Variable WebBrowserTitle nutzen, um die Aktualisierung Ihres Codes zu erleichtern, wenn Sie Ihren bevorzugten Webbrowser ändern oder wenn sich der Titel oder die Fensterklasse aufgrund eines Software-Updates ändert.

In AutoHotkey werden Variablen erstellt, sobald sie verwendet werden. Jede Variable ist nicht dauerhaft auf einen einzigen Datentyp beschränkt, sondern kann stattdessen einen Wert beliebigen Typs enthalten: Zeichenkette, Zahl oder Objekt. Jede Variable ist zunächst leer; d.h. jede neue Variable enthält eine leere Zeichenkette, bis ihr ein anderer Wert zugewiesen wird.

Eine Variable hat drei Hauptaspekte:

Für Variablennamen gelten einige Einschränkungen - Einzelheiten finden Sie unter Namen. Kurz gesagt ist es am sichersten, Namen zu verwenden, die aus ASCII-Buchstaben (nicht Groß-/Kleinschreibung-sensitiv), Ziffern und Unterstrichen bestehen, und Namen zu vermeiden, die mit einer Ziffer beginnen.

Ein Variablenname hat einen Gültigkeitsbereich, der definiert, wo im Code dieser Name verwendet werden kann, um auf diese bestimmte Variable zu verweisen; mit anderen Worten, wo die Variable sichtbar ist. Wenn eine Variable in einem bestimmten Gültigkeitsbereich nicht sichtbar ist, kann derselbe Name auf eine andere Variable verweisen. Beide Variablen können gleichzeitig existieren, aber nur eine ist für jeden Teil des Skripts sichtbar. Globale Variablen sind im "globalen Bereich" (d.h. außerhalb von Funktionen) sichtbar, müssen aber in der Regel deklariert werden, um innerhalb einer Funktion sichtbar zu sein. Lokale Variablen sind nur innerhalb der Funktion sichtbar, die sie erzeugt hat.

Eine Variable kann als Behälter oder Speicherort für einen Wert betrachtet werden. In der Dokumentation wird der Wert einer Variable häufig als Inhalt der Variable bezeichnet. Bei x := 42 kann man auch sagen, dass die Variable x die Zahl 42 als Wert hat oder dass der Wert von x eine 42 ist.

Es ist wichtig zu wissen, dass eine Variable und ihr Wert nicht dasselbe sind. Zum Beispiel könnten wir sagen: "meinArray ist ein Array", aber was wir wirklich meinen, ist, dass meinArray eine Variable ist, die eine Referenz zu einem Array enthält. Wir nehmen eine Abkürzung, indem wir den Namen der Variable verwenden, um auf ihren Wert zu verweisen, aber "meinArray" ist eigentlich nur der Name der Variable; das Array-Objekt weiß nicht, dass es einen Namen hat, und könnte von vielen verschiedenen Variablen (bzw. Namen) referenziert werden.

Uninitialisierte Variablen

Eine Variable zu initialisieren bedeutet, ihr einen Startwert zuzuweisen. Obwohl das Programm alle Variablen automatisch initialisiert (standardmäßig mit einer leeren Zeichenkette), sollte ein Skript seine Variablen immer initialisieren, bevor es sie verwendet. Auf diese Weise kann jeder, der das Skript liest, sehen, welche Variablen das Skript verwenden wird und welche Startwerte sie erwartungsgemäß haben werden.

Normalerweise muss das Skript jede Variable initialisieren, die eine Zahl enthalten soll. Zum Beispiel wird x := x + 1 nicht funktionieren, wenn x noch nie einen Wert zugewiesen bekommen hat, da die leere Zeichenkette als nicht-numerisch angesehen wird. Das Skript sollte ihr einen Startwert zuweisen, wie z.B. x := 0. Es gibt Fälle, wo leere Werte als 0 behandelt werden, aber man sollte sich besser nicht darauf verlassen.

IsSet kann verwendet werden, um zu prüfen, ob eine Variable initialisiert wurde, z.B. um eine globale oder statische Variable bei der ersten Verwendung zu initialisieren.

Skriptautoren können die #Warn-Direktive nutzen, um uninitialisierte Variablen in einem Skript zu finden.

Interne Variablen

Eine Vielzahl von Variablen sind fest in das Programm integriert und können normal referenziert werden. Solche Variablen, außer Clipboard, ErrorLevel und Befehlszeilenparameter, sind schreibgeschützt, d.h. ihr Inhalt kann nicht geändert werden. Konventionsgemäß beginnen die meisten dieser Variablen mit dem Präfix A_, daher ist es am besten, dieses Präfix nicht für eigene Variablen zu verwenden.

Einige Variablen wie A_KeyDelay und A_TitleMatchMode spiegeln Einstellungen wider, die das Verhalten des Skripts steuern, und separate Werte für jeden Thread aufbewahren. Dadurch können Subroutinen, die von neuen Threads gestartet werden (z.B. für Hotkeys, Menüs, Timer und so weiter), Einstellungen ändern, ohne andere Threads zu beeinflussen.

Einige spezielle Variablen werden nicht periodisch aktualisiert, sondern ihr Wert wird abgerufen oder berechnet, wenn das Skript auf die Variable verweist. Eine solche Variable ist zum Beispiel Clipboard, die den aktuellen Inhalt der Zwischenablage abruft, oder A_TimeSinceThisHotkey, die die Anzahl der Millisekunden berechnet, die seit dem Drücken des Hotkeys vergangen sind.

Siehe auch: Liste von internen Variablen.

Umgebungsvariablen

Umgebungsvariablen werden vom Betriebssystem verwaltet. Sie können sich eine Liste von Umgebungsvariablen anzeigen lassen, indem Sie SET in die Windows-Konsole eingeben und ENTER drücken.

Mit EnvSet kann eine neue Umgebungsvariable erstellt oder der Inhalt einer vorhandenen Umgebungsvariable geändert werden. Solche Ergänzungen und Änderungen sind nur für das Skript sichtbar und werden vom Rest des Systems ignoriert. Allerdings erben alle Programme oder Skripte, die das Skript über Run oder RunWait startet, in der Regel eine Kopie der Umgebungsvariablen des übergeordneten Skripts.

Es wird empfohlen, dass alle neuen Skripte Umgebungsvariablen wie Path über EnvGet abrufen:

EnvGet, AusgabeVar, Path  ; Zur Erklärung siehe #NoEnv.

Fehlt die #NoEnv-Direktive in einem Skript, wird beim Lesen einer leeren Variable stattdessen der Wert der Umgebungsvariable mit diesem Namen zurückgeben, falls eine solche existiert. Dies kann zu Verwirrung führen, daher wird empfohlen, dass alle neuen Skripte #NoEnv verwenden.

Caching

Obwohl eine Variable üblicherweise dazu gedacht ist, einen einzelnen Wert zu enthalten, und dieser Wert einen bestimmten Typ (Zeichenkette, Zahl oder Objekt) hat, wandelt AutoHotkey automatisch zwischen Zahlen und Zeichenketten bei Fällen wie meineZkette + 1 und MsgBox %meineZahl% um. Da solche Umwandlungen sehr häufig vorkommen können, wird jedes Mal, wenn eine Variable umgewandelt wird, das Ergebnis in der Variable zwischengespeichert.

Tatsächlich kann eine Variable gleichzeitig sowohl eine Zeichenkette als auch eine Zahl enthalten. Normalerweise verbessert das die Performanz des Skripts ohne Nachteile, aber wenn eine Variable sowohl eine Zahl als auch eine Zeichenkette enthält, ist sie dann eine Zahl oder eine Zeichenkette? Diese Mehrdeutigkeit führt in mindestens zwei Fällen zu unerwartetem Verhalten:

  1. COM-Objekte. Um Parameter an ein COM-Objekt zu übergeben, muss das Programm den Inhalt der Variable in eine Zahl oder Zeichenkette umwandeln. Einige COM-Objekte lösen eine Ausnahme aus, wenn der falsche Wertetyp übergeben wird. Wenn eine Variable beide Wertetypen hat, wird die Zahl verwendet. Normalerweise führt das zum richtigen Ergebnis, manchmal aber auch nicht.
  2. Objekte haben nicht die Möglichkeit, gleichzeitig sowohl eine Zahl als auch eine Zeichenkette als Schlüssel oder Wert zu speichern. Da Zahlen speichereffizienter sind, wird, wenn eine Variable beide Wertetypen hat, die Zahl verwendet (außer bei Floating-Point-Zahlen, die als Schlüssel verwendet werden).

Der Slow-Modus von SetFormat bewirkt, dass beim Zuweisen einer reinen Zahl diese Zahl in eine Zeichenkette umgewandelt wird. Bei Integern wird die Zahl ebenfalls gespeichert, daher hat das keine negativen Auswirkungen außer auf die Performanz. Bei Floating-Point-Zahlen wird die Zahl nicht gespeichert, da SetFormat die Genauigkeit des Wertes beeinflusst und eventuell sogar alle Dezimalstellen wegkürzt. Mit anderen Worten, der Slow-Mode von SetFormat verhindert, dass reine Floating-Point-Zahlen in Variablen gespeichert werden.

Wenn man die Adresse einer Variable nimmt, wird der Wert der Variable direkt in eine Zeichenkette umgewandelt und das Caching deaktiviert, bis sich die Adresse der Variable ändert (was passiert, wenn sich ihre Kapazität ändert). Das liegt zum einen an der Abwärtskompatibilität und zum anderen daran, dass das Skript den Wert jederzeit indirekt über die Adresse ändern kann, was den Cache ungenau macht.

Funktionen/Befehle

Eine Funktion oder ein Befehl ist das Werkzeug des Skripts, um etwas zu tun.

Im Grunde sind Funktionen und Befehle dasselbe, daher gelten für beide die hier beschriebenen Konzepte. Die lange Geschichte von AutoHotkey v1 und das Streben nach Abwärtskompatibilität haben jedoch zu einer Trennung zwischen Befehlen, die die Legacy-Syntax erfordern, und Funktionen, die die Ausdruckssyntax erfordern, geführt.

Befehle und Funktionen können viele verschiedene Zwecke haben. Einige Funktionen könnten nur eine einfache Berechnung durchführen, während andere sofort sichtbare Effekte erzielen, wie z.B. das Verschieben eines Fensters. Eine der Stärken von AutoHotkey ist die einfache Möglichkeit, andere Programme zu automatisieren und viele andere häufige Aufgaben durch einfaches Aufrufen einiger weniger Funktionen zu erledigen. Beispiele finden Sie in der Befehls- und Funktionsliste.

In dieser Dokumentation werden einige gebräuchliche Wörter in einer Weise verwendet, die für jemanden ohne Vorkenntnisse nicht offensichtlich ist. Nachfolgend finden Sie einige dieser Wörter/Phrasen, die häufig im Zusammenhang mit Funktionen und Befehle verwendet werden:

Befehle oder Funktionen aufrufen

Der Aufruf von Funktionen oder Befehlen bewirkt, dass das Programm diese startet, ausführt oder auswertet. Mit anderen Worten, ein Funktionsaufruf überträgt vorübergehend die Kontrolle vom Skript auf die Funktion. Wenn die Funktion ihren Zweck erfüllt hat, überträgt sie die Kontrolle via Return wieder auf das Skript. Das heißt, dass jeglicher Code nach dem Funktionsaufruf erst dann ausgeführt wird, wenn die Funktion ihr Ende erreicht hat.

Es kann jedoch vorkommen, dass Funktionen oder Befehle abgeschlossen sind, bevor ihre Auswirkungen für den Benutzer sichtbar werden. Zum Beispiel kann der Send-Befehl seine Tastendrücke bereits gesendet haben, bevor die Tastendrücke ihr Ziel erreicht und die gewünschte Wirkung erzielt haben.

Parameter

Normalerweise akzeptieren Befehle oder Funktionen einen oder mehrere Parameter, die angeben, wie oder womit sie agieren sollen. Jeder Parameter ist ein Wert, z.B. eine Zeichenkette oder Zahl. Die Parameter von WinMove legen z.B. fest, welches Fenster wohin verschoben werden soll. Parameter werden auch als Argumente bezeichnet. Gängige Abkürzungen sind Param und Arg.

Parameter übergeben

Parameter werden an eine Funktion oder an einen Befehl übergeben, d.h. für jeden Parameter der Funktion oder des Befehls ist beim Aufrufen ein Wert angegeben. Zum Beispiel können Sie den Namen einer Taste an GetKeyState übergeben, um festzustellen, ob diese Taste gedrückt gehalten wird.

Einen Wert zurückgeben

Funktionen geben einen Wert über Return zurück, daher wird das Ergebnis der Funktion oft als Rückgabewert bezeichnet. Zum Beispiel gibt StrLen() die Anzahl der Zeichen zurück, die in einer Zeichenkette enthalten sind. Befehle geben ihr Ergebnis nicht direkt zurück, sondern speichern es in eine Variable. Funktionen können das auch tun, wenn sie z.B. mehr als ein Ergebnis zurückgeben müssen.

Funktionen und Befehle erwarten normalerweise ihre Parameter in einer bestimmten Reihenfolge, daher hängt die Bedeutung der einzelnen Parameterwerte von ihrer Position in der kommagetrennten Parameterliste ab. Einige Parameter können weg bzw. leer gelassen werden - in diesem Fall aber kann das darauffolgende Komma nur weggelassen werden, wenn alle übrigen Parameter ebenfalls weggelassen werden. Zum Beispiel hat ControlSend die folgende Syntax:

ControlSend, Steuerelement, Tasten , FensterTitel, FensterText, AusnahmeTitel, AusnahmeText

Die eckigen Klammern signalisieren, dass die darin enthaltenen Parameter optional sind (die Klammern selbst müssen im eigentlichen Code weggelassen werden). ControlSend ist jedoch nur dann sinnvoll, wenn Tasten und ggf. das Zielfenster angegeben sind. Zum Beispiel:

ControlSend, Edit1, ^{Home}, A  ; Korrekt. Steuerelement ist angegeben.
ControlSend, ^{Home}, A         ; Falsch: Parameter stimmen nicht überein.
ControlSend,, ^{Home}, A        ; Korrekt. Steuerelement wurde weggelassen.

Methoden

Methoden sind Funktionen, die zu einem bestimmten Objekt gehören. Während es zum Beispiel nur eine Funktion namens Send geben kann, können mehrere Objekte eine Methode namens Send mit unterschiedlichem Effekt haben. Aus diesem Grund wird das Zielobjekt (das eine Variable oder ein Teilausdruck sein kann) nicht in der Parameterliste, sondern links neben dem Methodennamen angegeben. Weitere Informationen finden Sie unter Objektorientierte Schnittstelle.

Kontrollfluss

Der Kontrollfluss ist die Reihenfolge, in der die einzelnen Anweisungen ausgeführt werden. Im Normalfall werden Anweisungen der Reihe nach von oben nach unten ausgeführt, aber dieses Verhalten kann mit einer Kontrollanweisung manipuliert werden, z.B. indem Anweisungen wiederholt ausgeführt werden, oder nur ausgeführt werden, wenn eine bestimmte Bedingung erfüllt ist.

Anweisung

Eine Anweisung ist einfach gesagt das kleinste eigenständige Element der Sprache, das eine ausführende Aktion ausdrückt. Anweisungen in AutoHotkey sind Befehle, Zuweisungen, Funktionsaufrufe und andere Ausdrücke. Direktiven, Labels (einschließlich Hotkeys und Hotstrings) und Deklarationen ohne Zuweisungen sind dagegen keine Anweisungen; sie werden nach dem Programmstart und vor dem Ausführen des Skripts abgearbeitet.

Ausführen

Ausführen, Durchführen, Auswerten, Umsetzen und so weiter. Ausführen hat grundsätzlich die gleiche Bedeutung wie im normalen Sprachgebrauch.

Körper

Der Körper einer Kontrollanweisung ist die Anweisung oder Anweisungsgruppe, zu der sie gehört. Zum Beispiel wird der Körper einer if-Anweisung nur ausgeführt, wenn eine bestimmte Bedingung erfüllt ist.

Schauen Sie sich zum Beispiel die folgenden Instruktionen an:

  1. Öffne Notepad
  2. Warte, bis Notepad auf dem Bildschirm erscheint
  3. Schreibe "Hallo, Welt!"

Wir machen einen Schritt nach dem anderen, und wenn dieser Schritt beendet ist, gehen wir zum nächsten Schritt über. So ähnlich erfolgt auch der Kontrollfluss in einem Programm oder Skript normalerweise von einer Anweisung zur nächsten. Was aber, wenn wir etwas in ein existierendes Notepad-Fenster schreiben wollen? Schauen Sie sich die folgenden überarbeiteten Instruktionen an:

  1. Wenn Notepad nicht läuft:
    1. Öffne Notepad
    2. Warte, bis Notepad auf dem Bildschirm erscheint
  2. Andernfalls:
    1. Aktiviere Notepad
  3. Schreibe "Hallo, Welt!"

Wir öffnen also entweder Notepad oder aktivieren Notepad, je nachdem, ob es bereits läuft. Punkt 1 ist eine bedingte Anweisung, auch bekannt als if-Anweisung, d.h. wir führen ihren Körper (Punkt 1.1 bis Punkt 1.2) nur aus, wenn eine Bedingung erfüllt ist. Punkt 2 ist eine else-Anweisung; wir führen ihren Körper (Punkt 2.1) nur aus, wenn die Bedingung einer vorherigen if-Anweisung nicht erfüllt ist. Je nach Bedingung erfolgt der Kontrollfluss auf eine von zwei Arten: Punkt 1 (if true) → Punkt 1.1 → Punkt 1.2 → Punkt 3; oder Punkt 1 (if false) → Punkt 2 (else) → Punkt 2.1 → Punkt 3.

Die obigen Instruktionen können in den folgenden Code umgewandelt werden:

if (not WinExist("ahk_class Notepad"))
{
    Run Notepad
    WinWait ahk_class Notepad
}
else
    WinActivate ahk_class Notepad
Send Hallo`, Welt{!}

In unseren schriftlichen Instruktionen haben wir Einrückungen und Nummerierungen verwendet, um die Anweisungen zu gruppieren. Skripte funktionieren etwas anders. Einrückungen verbessern zwar die Lesbarkeit des Codes, haben aber keinen Einfluss auf die Gruppierung von Anweisungen in AutoHotkey. Stattdessen werden Anweisungen gruppiert, indem man sie, wie oben gezeigt, mit geschweiften Klammern umschließt. Dies wird als Block bezeichnet.

Details zur Syntax - also wie man Kontrollanweisungen in AutoHotkey schreibt oder erkennt - finden Sie unter Kontrollfluss.

Details

Zeichenkettenkodierung

Jedes Zeichen in der Zeichenkette entspricht einer Zahl, auch Ordinalzahl genannt, oder einem Zeichencode. Zum Beispiel würde der Wert "Abc" wie folgt dargestellt werden:

Abc
6598990

Kodierung: Die Kodierung einer Zeichenkette definiert, wie Symbole mit den Ordinalzahlen und Ordinalzahlen mit den Bytes verknüpft werden. Es gibt viele verschiedene Kodierungen, aber da alle Kodierungen, die von AutoHotkey unterstützt werden, ASCII als Untermenge enthalten, haben die Zeichencodes 0 bis 127 immer die gleiche Bedeutung. So hat zum Beispiel 'A' immer den Zeichencode 65.

Nullterminierung: Jede Zeichenkette wird mit einem "Nullzeichen" terminiert; solche Zeichen haben den Binärwert Null und markieren das Ende einer Zeichenkette. Die Länge der Zeichenkette muss nicht gespeichert werden, da die Länge über die Position des Nullterminators abgeleitet werden kann. Aus Performanzgründen speichert AutoHotkey manchmal die Länge, z.B. wenn eine Zeichenkette in einer Variable enthalten ist.

Hinweis: Da AutoHotkey v1 auf die Nullterminierung angewiesen ist, unterstützt es grundsätzlich keine Zeichenketten mit eingebetteten Nullzeichen. Solche Zeichenketten können zwar mit VarSetCapacity() und NumPut() oder DllCall() erzeugt werden, führen aber meist zu inkonsistenten Ergebnissen.

Native Kodierung: Obwohl AutoHotkey den Umgang mit Texten unterschiedlicher Kodierung ermöglicht, setzen die internen Befehle und Funktionen - und bis zu einem gewissen Grad auch die Sprache selbst - voraus, dass Zeichenkettenwerte in einer bestimmten Kodierung vorliegen. Dies wird als native Kodierung bezeichnet. Die native Kodierung hängt von der Version von AutoHotkey ab:

Zeichen: In der Regel wird in anderen Abschnitten dieser Dokumentation der Begriff "Zeichen" für die kleinste Einheit einer Zeichenkette verwendet; Bytes für ANSI-Zeichenketten und 16-Bit-Codeeinheiten für Unicode-Zeichenketten (UTF-16). Aus praktischen Gründen werden die Länge einer Zeichenkette und die Positionen innerhalb einer Zeichenkette in diesen festen Einheiten gemessen, auch wenn sie nicht immer vollständige Unicode-Zeichen sind.

FileRead, FileAppend, FileOpen() und das File-Objekt bieten Möglichkeiten, um Text mit einer bestimmten Kodierung aus/in eine Datei zu lesen/schreiben.

Die Funktionen StrGet und StrPut können verwendet werden, um die native Kodierung einer Zeichenkette in eine andere umzuwandeln, und umgekehrt. Diese Funktionen sind jedoch in der Regel nur in Kombination mit Datenstrukturen und der DllCall-Funktion sinnvoll. Zeichenketten, die direkt an oder von DllCall() übergeben werden, können mit den Parametertypen AStr oder WStr in ANSI oder UTF-16 umgewandelt werden.

Techniken zum Umgang mit den Unterschieden zwischen ANSI- und Unicode-Versionen von AutoHotkey finden Sie unter Unicode vs. ANSI.

Reine Zahlen

Eine reine oder binäre Zahl ist eine Zahl im Speicher, mit deren Format die CPU des Computers direkt umgehen kann, um z.B. Berechnungen durchzuführen. In den meisten Fällen wandelt AutoHotkey automatisch zwischen numerischen Zeichenketten und reinen Zahlen um, aber nur selten muss AutoHotkey zwischen den beiden Typen unterscheiden. AutoHotkey verwendet hauptsächlich zwei Datentypen für reine Zahlen:

Mit anderen Worten gelten für Skripte folgende Einschränkungen:

Hinweis: Es gibt einige Dezimalstellen, die das binäre Floating-Point-Format nicht exakt darstellen kann, so dass eine Zahl auf die nächstliegende darstellbare Zahl gerundet wird. Das kann zu unerwarteten Ergebnissen führen. Zum Beispiel:

SetFormat FloatFast, 0.17  ; Zeige "übervolle" Präzision
MsgBox % 0.1 + 0           ; 0.10000000000000001
MsgBox % 0.1 + 0.2         ; 0.30000000000000004
MsgBox % 0.3 + 0           ; 0.29999999999999999
MsgBox % 0.1 + 0.2 = 0.3   ; 0 (nicht identisch)

Eine Strategie zur Lösung dieses Problems besteht darin, den direkten Vergleich zu vermeiden und stattdessen die Differenz zu vergleichen. Zum Beispiel:

MsgBox % Abs((0.1 + 0.2) - (0.3)) < 0.0000000000000001

Eine andere Strategie besteht darin, die Zahl vor dem Vergleich immer in eine Zeichenkette umzuwandeln (und dabei Rundungen vorzunehmen). In der Regel gibt es dafür zwei Möglichkeiten unter Angabe der Genauigkeit:

MsgBox % Round(0.1 + 0.2, 15) = Format("{:.15f}", 0.3)

Namen

AutoHotkey wendet die gleichen Regeln für die Benennung verschiedener Dinge an, inklusive Variablen, Funktionen, Fenstergruppen, GUIs, Klassen und Methoden:

Aufgrund von Gestaltungsrichtlinien ist es grundsätzlich besser, nur Buchstaben, Zahlen und Unterstriche zu verwenden (zum Beispiel: PositionZeiger, Gesamt_Elemente und Eintrag_ist_gültig). Auf diese Weise können Personen, die mit anderen Computersprachen vertraut sind, Ihr Skript besser verstehen.

Obwohl der Name einer Variable vollständig aus Ziffern bestehen kann, sind solche Namen in der Regel nur für eingehende Befehlszeilenparameter relevant. Ausdrücke dürfen keine numerischen Namen enthalten, weil sie dort nicht als Variablen, sondern als Zahlen interpretiert werden. Vermeiden Sie am besten Namen, die mit einer Ziffer beginnen, da solche Namen verwirrend sind und in AutoHotkey v2 als ungültig behandelt werden.

Da die folgenden Zeichen in AutoHotkey v2 eventuell für andere Zwecke reserviert werden, ist es ratsam, diese nicht zu verwenden: # @ $

Für Eigenschaftsnamen in Klassen gelten die gleichen Regeln und Einschränkungen wie für Variablennamen, mit der Ausnahme, dass die drei oben genannten Zeichen (# @ $) nicht erlaubt sind. Diese können zwar in einer Methodendefinition verwendet werden, aber dann kann diese Methode nur mit eckigen Klammern aufgerufen werden. Zum Beispiel ist meinObjekt.@home() ungültig, aber meinObjekt["@home"]() gültig.

Variablenreferenzen vs. Werte

Variablen haben einige Attribute, die die Grenze zwischen einer Variable und ihrem Wert verschwimmen lassen, dennoch ist es wichtig, sie zu differenzieren. Insbesondere in Bezug auf Objekte und ByRef-Parametern.

Obwohl wir sagen können, dass die Variable meinArray ein Array enthält (was ein Objekttyp ist), ist das, was die Variable enthält, nicht das Array selbst, sondern eher eine Referenz bzw. ein Pointer zum Array. Es können beliebig viele Variablen eine Referenz zum selben Objekt enthalten. In diesem Fall kann es hilfreich sein, sich eine Variable nur als Namen vorzustellen. Gibt man zum Beispiel einer Person einen Spitznamen, führt das nicht dazu, dass diese Person geklont wird.

Standardmäßig werden Variablen via Wert an benutzerdefinierte Funktionen übergeben. Das heißt, dass der in der Variable enthaltene Wert in eine Variable kopiert wird, die dem Parameter der Funktion entspricht. Ein ByRef-Parameter kann verwendet werden, um eine Variable via Referenz zu übergeben, oder anders gesagt, um einen Parameter der Funktion zu einem Alias für die Variable zu machen, so dass die Funktion der Variable einen neuen Wert zuweisen kann.

Da eine Variable nicht das Objekt selbst, sondern nur eine Referenz zu diesem Objekt enthält, empfängt die Funktion, während so eine Variable an einen ByRef-losen Parameter übergeben wird, eine Referenz zum selben Objekt. Die Funktion kann dadurch das Objekt modifizieren, aber nicht die Variable, die der Funktionsaufrufer übergeben hat, weil die Funktion nicht die Variable, sondern nur eine Referenz zum Objekt hat.

Objektreferenzen

Skripte interagieren nur indirekt mit einem Objekt, via Referenz zum Objekt. Beim Erstellen eines Objekts wird es an einem Ort erstellt, den Sie nicht kontrollieren können, und Ihnen eine Referenz übergeben. Wenn Sie diese Referenz an eine Funktion übergeben oder in eine Variable oder in einem anderen Objekt speichern, wird eine neue Referenz zum selben Objekt erstellt. Um eine Referenz freizugeben, verwenden Sie einfach eine Zuweisung und ersetzen Sie sie mit einem anderen Wert. Ein Objekt wird erst gelöscht, wenn alle Referenzen freigegeben sind, d.h. es ist weder möglich noch sollte versucht werden, ein Objekt explizit zu löschen.

Ref1 := Object()  ; Ein Objekt erstellen und die erste Referenz speichern
Ref2 := Ref1      ; Eine neue Referenz zum selben Objekt erstellen
Ref1 := ""        ; Die erste Referenz freigeben
Ref2 := ""        ; Die zweite Referenz freigeben; Objekt wird gelöscht

Sollten Sie das nicht verstehen, versuchen Sie, sich ein Objekt als Mietwohnung vorzustellen. Wenn Sie eine Wohnung mieten, erhalten Sie einen Schlüssel, mit dem sie die Wohnung betreten können. Sie können weitere Schlüssel erhalten und damit die Wohnung betreten, aber wenn Sie die Wohnung nicht mehr benötigen, müssen Sie alle Schlüssel an den Vermieter zurückgeben. In der Regel wird eine Wohnung nicht gelöscht, aber vielleicht muss der Vermieter jemanden beauftragen, den Müll, den Sie hinterlassen haben, zu entfernen; ähnlich dem Fall, dass die hinterlegten Werte in einem Objekt freigegeben werden, wenn das Objekt gelöscht wird.