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 davon ausgegangen, dass der Leser über Vorkenntnisse in Scripting oder Programmierung verfügt, aber er sollte für neue Fachbegriffe offen 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 einzelne Entität gesehen werden. Die Länge einer Zeichenkette repräsentiert die 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 vom Verketten mit einer in Anführungszeichen gesetzte Zeichenkette) wird allerdings nie als numerisch gewertet, wenn sie direkt in einem Ausdruck verwendet wird.

Wie literaler (direkt geschriebener) Text innerhalb des Skripts geschrieben werden soll, hängt vom Kontext ab. Weitere Informationen finden Sie unter Altmodische Syntax und Zeichenketten (in Ausdrücken).

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

Zahlen

AutoHotkey unterstützt folgende Zahlenformate:

Hexadezimale Zahlen müssen das 0x- oder 0X-Präfix verwenden, wenn nicht anders in der Dokumentation vermerkt. Dieses Präfix muss nach einem Vorzeichen wie + oder -, falls vorhanden, und vor beginnenden Nullen erfolgen. Zum Beispiel wäre 0x001 gültig, aber nicht 000x1.

Zahlen, die mit einem Dezimalpunkt geschrieben werden, gelten immer als Floating-Point-Zahlen, auch wenn die Nachkommastelle eine Null ist. 42 und 42.0 beispielsweise sind in der Regel das gleiche, aber dies trifft nicht immer zu. Die wissenschaftliche Schreibweise wird ebenfalls erkannt, allerdings 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 je nach aktuellem Integer- oder Float-Format formatiert. Obwohl der SetFormat-Befehl genutzt werden kann, um das aktuelle Format zu ändern, ist es in der Regel besser, die Format-Funktion zu nutzen, um eine Zeichenkette zu formatieren. 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 genutzt, um etwas wiederzugeben, das exakt zwei mögliche Zustände hat, wie z. B. die Wahrheit eines Ausdrucks. Der Ausdruck (x <= y) beispielsweise wäre True bzw. wahr, 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, deshalb verwendet es den Integer-Wert 0 für False und 1 für True. Wenn ein Wert entweder True oder False sein muss, wird ein leerer Wert oder ein Wert von 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 und 0 enthalten. Sie können verwendet werden, um ein Skript besser lesbar zu machen.

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 einer Länge von 0) diese Bedeutung.

Wenn eine Variable oder ein Parameter als "leer" bezeichnet wird, meint man damit in der Regel eine leere Zeichenkette (eine Zeichenkette mit einer Länge von 0).

Objekte

Grundsätzlich gibt es zwei Ansichten von Objekten:

Die richtige Verwendung von Objekten (und insbesondere von Klassen) kann zu einem modularen und wiederverwendbaren Code verhelfen. Modularer Code ist in der Regel einfacher zu testen, zu verstehen und zu pflegen. So kann man z. B. einen Codeabschnitt verbessern oder modifizieren, ohne die Details anderer Abschnitte kennen zu müssen und ohne entsprechende Änderungen an diesen Abschnitten vornehmen zu müssen. Wiederverwendbarer Code spart Zeit, weil er das Schreiben und Testen von Code für gleiche oder ähnliche Aufgaben überflüssig macht.

Wenn eine Variable ein Objekt zugewiesen bekommt, z. B. meinObj := {}, wird nicht das Objekt selbst, sondern eine Referenz zu diesem Objekt gespeichert. Kopiert man diese Variable, z. B. 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). Für gewöhnlich 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 werden durch drei verschiedene Muster angegeben: .Name, [Parameter] und (Parameter), 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] untereinander getauscht oder kombiniert werden:

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

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

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

Beachten Sie, dass Name, sofern vorhanden, zum ersten Parameter wird. meinObj.Name ist das gleiche wie meinObj["Name"], während meinObj.123 das gleiche wie meinObj[123] ist. Dies gilt für jeden Objekttyp, daher ist es jederzeit möglich, den Namen einer Eigenschaft oder Methode zu berechnen, während das Skript läuft, anstatt ihn direkt in das Skript einzufügen.

Obwohl Name oder Param1 als erster Parameter betrachtet wird, sollten Sie daran denken, dass es sich hierbei nur um Meldungen handelt, und das dem Objekt freigestellt ist, mit ihnen in irgendeiner Weise zu interagieren. In einem Methodenaufruf wie oben gezeigt verwendet das Objekt normalerweise Name oder Param1, um zu identifizieren, welche Methode aufgerufen werden soll, und Param2 und so weiter, um sie der Methode zu übergeben. In diesem Fall ist Param2 in Wirklichkeit der erste Parameter der Methode.

Im Allgemeinen 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 Skript-Autoren fast nie relevant. Im Allgemeinen kann man es sich einfach als "der zugeordnete Wert" vorstellen.

Variablen

Eine Variable ermöglicht es Ihnen, einen Namen als Platzhalter für einen Wert zu verwenden. Diesen Wert können Sie jederzeit ändern, während das Skript läuft. 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). Auch eine Variable, der nur einmal ein Wert zugewiesen wird, kann 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 durch ein Software-Update ändert.

In AutoHotkey werden Variablen erstellt, sobald man sie verwendet. Jede Variable ist nicht permanent auf einen einzelnen Datentyp beschränkt, sondern kann stattdessen einen Wert beliebigen Typs enthalten: Zeichenkette, Zahl oder Objekt. Jede Variable ist vorerst leer; das heißt, dass jede neu erstellte Variable eine leere Zeichenkette enthält, bis ihr ein anderer Wert zugewiesen wird.

Eine Variable hat drei Hauptaspekte:

Einem Variablennamen sind Beschränkungen auferlegt - siehe Namen für Details. Kurz gesagt, es ist am sichersten, sich an Namen zu halten, 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 genutzt werden kann, um auf diese bestimmte Variable zu verweisen; mit anderen Worten, wo die Variable sichtbar ist. Wenn eine Variable innerhalb eines bestimmten Gültigkeitsbereichs nicht sichtbar ist, kann derselbe Name auf eine andere Variable verweisen. Beide Variablen können zur gleichen Zeit existieren, aber nur eine ist für jeden Teil des Skripts sichtbar. Globale Variablen sind im "globalen Bereich" (also außerhalb von Funktionen) sichtbar, die aber in der Regel deklariert werden müssen, um sie innerhalb einer Funktion sichtbar zu machen. Lokale Variablen sind nur innerhalb der Funktion sichtbar, die sie erzeugt hat.

Eine Variable kann als Container oder Speicherort für einen Wert angesehen werden. In der Dokumentation werden Sie häufig darauf stoßen, dass der Wert einer Variable als Inhalt der Variable bezeichnet wird. Bei einer Variable 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. von vielen Namen) angesprochen werden.

Nicht initialisierte Variablen

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

Normalerweise ist es notwendig, dass das Skript jede Variable initialisiert, die eine Zahl enthalten soll. x := x + 1 beispielsweise wird nicht funktionieren, wenn x noch nie einen Wert zugewiesen bekam, da die leere Zeichenkette als nicht-numerisch angesehen wird. Das Skript sollte ihr einen Startwert zuweisen, wie z. B. x := 0. Es gibt einige Fälle, wo leere Werte als 0 behandelt werden, aber es ist besser, sich nicht darauf zu verlassen.

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

Skript-Autoren können die #Warn-Direktive nutzen, um Instanzen zu finden, wo das Skript eine Variable noch nicht initialisiert hat.

Interne Variablen

Eine Vielzahl von Variablen ist fest in das Programm integriert und normal abrufbar. Solche Variablen, außer Clipboard, ErrorLevel und Befehlszeilenparameter, sind schreibgeschützt; das heißt, dass man ihren Inhalt nicht ändern kann. Gemäß der Konvention 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, wenn Sie in der Windows-Konsole SET 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 im restlichen System ignoriert. Allerdings erben alle Programme oder Skripte, die das Skript via Run oder RunWait startet, in der Regel eine Kopie der Umgebungsvariablen des übergeordneten Skripts.

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

EnvGet, AusgabeVar, Path  ; Zur Erläuterung, siehe #NoEnv.

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

Caching

Obwohl eine Variable üblicherweise zum Speichern eines einzelnen Wertes gedacht ist, 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 zur selben Zeit sowohl eine Zeichenkette als auch eine Zahl enthalten. Normalerweise verbessert das die Leistung des Skripts ohne Nachteile, aber wenn eine Variable sowohl eine Zahl als auch eine Zeichenkette enthält, ist es nun eine Zahl oder ist es 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 erhält man damit das richtige Ergebnis, manchmal aber auch nicht.
  2. Objekte haben nicht die Möglichkeit, 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 dies keine nachteiligen Auswirkungen außer auf die Leistung. Bei Floating-Point-Zahlen wird die Zahl nicht gespeichert, da SetFormat die Genauigkeit des Wertes beeinflusst und eventuell sogar alle Nachkommastellen wegkürzt. Mit anderen Worten verhindert der Slow-Mode von SetFormat, 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 (dies geschieht, wenn sich ihre Kapazität ändert). Das liegt zum einen an der Abwärtskompatibilität und zum anderen daran, dass das Skript den Wert über seine Adresse jederzeit indirekt ä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, deshalb gelten die hier erläuterten Konzepte für beide. Die lange Geschichte von AutoHotkey v1 und die Ausrichtung zur Abwärtskompatibilität haben jedoch zu einer Trennung zwischen Befehlen, die die altmodische Syntax erfordern, und Funktionen, die eine Ausdruckssyntax erfordern, geführt.

Befehle und Funktionen haben unterschiedliche Einsatzmöglichkeiten. Einige Funktionen führen lediglich eine einfache Berechnung durch, während andere sofort sichtbare Effekte erzielen, wie z. B. das Verschieben eines Fensters. Eine der Stärken von AutoHotkey ist die Leichtigkeit, mit der Skripte andere Programme automatisieren und viele andere häufige Aufgaben erledigen können, indem man einfach nur ein paar Funktionen aufruft. Beispiele finden Sie in der Befehls- und Funktionsliste.

In dieser Dokumentation werden einige gebräuchliche Wörter auf eine Art und Weise verwendet, die für jemanden ohne Vorkenntnisse nicht offensichtlich ist. Nachfolgend finden Sie einige solcher Wörter/Phrasen, die häufig in Bezug auf Funktionen und Befehle genutzt werden:

Ein Befehl oder eine Funktion aufrufen

Der Aufruf von Funktionen oder Befehlen bewirkt, dass das Programm diese startet, ausführt oder auswertet. Das heißt, dass ein Funktionsaufruf die Kontrolle des Skripts vorübergehend an die Funktion übergibt. Wenn die Funktion ihren Zweck erfüllt hat, gibt sie die Kontrolle via Return wieder an das Skript zurück. Das heißt, dass jeglicher Code nach dem Funktionsaufruf erst ausgeführt wird, wenn die Funktion ihr Ende erreicht hat.

Manchmal ist es jedoch so, dass eine Funktion oder ein Befehl abgeschlossen ist, bevor ihre Auswirkungen für den Benutzer sichtbar werden. Zum Beispiel könnte der Send-Befehl bereits seine Tastendrücke gesendet haben, bevor sie überhaupt ihr Ziel erreicht und ihre gewollte Wirkung erzielt haben.

Parameter

Normalerweise akzeptieren Befehle oder Funktionen einen oder mehrere Parameter, die vorschreiben, wie oder womit sie agieren sollen. Jeder Parameter ist ein Wert, z. B. eine Zeichenkette oder Zahl. Die Parameter von WinMove beispielsweise bestimmen, 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; das heißt, dass für jeden Parameter der Funktion oder des Befehls beim Aufrufen ein Wert angegeben ist. Zum Beispiel kann man den Namen einer Taste an GetKeyState() übergeben, um festzustellen, ob diese Taste gedrückt gehalten wird.

Einen Wert zurückgeben

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

Funktionen und Befehle erwarten normalerweise, dass Parameter in einer bestimmten Reihenfolge geschrieben werden, deshalb ist die Bedeutung der einzelnen Parameterwerte abhängig von ihrer Position in der via Komma getrennten Parameterliste. 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. Die Syntax für ControlSend lautet zum Beispiel:

ControlSend , Steuerelement, Tasten, FensterTitel, FensterText, IgnoriereTitel, IgnoriereText

Die eckigen Klammern signalisieren, dass die darin enthaltenen Parameter optional sind (die Klammern selbst sollten nicht im eigentlichen Code erscheinen). ControlSend ist jedoch nur dann sinnvoll, wenn Tasten und gegebenenfalls das Zielfenster angeben 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 sich auf ein bestimmtes Objekt auswirken. Während es nur eine Funktion mit dem Namen Send (zum Beispiel) geben kann, kann es genauso viele Methoden mit dem Namen Send geben, wie es Objekte gibt, da jedes Objekt (oder Klasse von Objekten) unterschiedlich reagieren kann. Aus diesem Grund wird das Zielobjekt (das eine Variable oder ein Teilausdruck sein kann) nicht innerhalb der Parameterliste, sondern auf der linken Seite des Methodennamens 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, allerdings kann dieses Verhalten mit einer Kontrollanweisung überschrieben werden, indem man Anweisungen z. B. wiederholt ausführen lässt, oder 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. In AutoHotkey sind Anweisungen Befehle, Zuweisungen, Funktionsaufrufe und andere Ausdrücke. Direktiven, Label (einschließlich Hotkeys und Hotstrings) und Deklarationen ohne Zuweisungen sind hingegen keine Anweisungen; sie werden verarbeitet, sobald das Programm startet und bevor das Skript ausgeführt wird.

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. Auf die gleiche Weise funktioniert üblicherweise der Kontrollfluss in einem Programm oder Skript - er geht die Anweisungen schrittweise durch. Aber was ist, wenn wir etwas in ein vorhandenes 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. Ansonsten:
    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; das heißt, dass wir ihren Körper (Punkt 1.1 bis Punkt 1.2) nur ausführen, 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 läuft die Steuerung auf zwei Arten ab: 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. Obwohl die Einrückung den Code besser lesbar macht, hat sie in AutoHotkey keinen Einfluss auf die Gruppierung von Anweisungen. 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

Zeichenkettencodierung

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

Abc
6598990

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

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

Hinweis: Aufgrund der Abhängigkeit von Null-Terminierung unterstützt AutoHotkey v1 grundsätzlich keine Zeichenketten mit eingebetteten Nullzeichen. Solche Zeichenketten können zwar mit VarSetCapacity() und NumPut() oder DllCall() erstellt werden, führen aber meistens zu inkonsistenten Ergebnissen.

Native Codierung: Obwohl AutoHotkey Möglichkeiten bereitstellt, Texte mit unterschiedlichen Codierungen zu bearbeiten, gehen die internen Befehle und Funktionen -- und bis zu einem gewissen Grad auch die Sprache selbst -- davon aus, dass Zeichenkettenwerte in einer bestimmten Codierung vorliegen. Dies wird als native Codierung bezeichnet. Die native Kodierung hängt von der Version von AutoHotkey ab:

Zeichen: In der Regel verwenden andere Bereiche dieser Dokumentation den Begriff "Zeichen" für die kleinste Einheit einer Zeichenkette; 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 anhand dieser festen Größen gemessen, auch wenn es sich dabei möglicherweise nicht um vollständige Unicode-Zeichen handelt.

FileRead, FileAppend, FileOpen() und das File-Objekt bieten Möglichkeiten, um den Text von Dateien mit einer bestimmten Codierung zu lesen und zu schreiben.

Die Funktionen StrGet und StrPut können genutzt werden, um Zeichenketten zwischen der nativen Codierung und einer anderen angegebenen Codierung umzuwandeln. 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 mithilfe der Parametertypen AStr oder WStr in ANSI oder UTF-16 umgewandelt werden.

Techniken, wie man mit den Unterschieden zwischen ANSI- und Unicode-Versionen von AutoHotkey umgehen kann, finden Sie unter Unicode vs ANSI.

Reine Zahlen

Eine reine oder binäre Zahl ist eine im Speicher enthaltene Zahl, 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, die nur selten unterschiedlich behandelt werden. AutoHotkey verwendet hauptsächlich zwei Datentypen für reine Zahlen:

Mit anderen Worten sind Skripte von folgenden Einschränkungen betroffen:

Hinweis: Es gibt einige Nachkommastellen, die das binäre Floating-Point-Format nicht exakt darstellen kann und die Zahl deshalb auf die nächstliegende darstellbare Zahl rundet. Dies 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 Bewältigung 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 ist es, vor dem Vergleich immer in eine Zeichenkette umzuwandeln (und dabei Rundungen vorzunehmen). Es gibt in der Regel zwei Möglichkeiten, dies zu tun, während Sie die Genauigkeit angeben:

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 in der Regel am besten, die Variablen nur mit Buchstaben, Zahlen und Unterstriche zu benennen (zum Beispiel: PositionZeiger, Gesamt_Elemente und Eintrag_ist_gültig). Dadurch können Leute, 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 können keine numerischen Namen enthalten, weil sie dort nicht als Variablen, sondern als Zahlen interpretiert werden. Am besten sollte man vermeiden, einen Namen mit einer Ziffer zu beginnen, da solche Namen verwirrend sind und in AutoHotkey v2 als ungültig angesehen werden.

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

Eigenschaftsnamen in Klassen haben die gleichen Regeln und Einschränkungen wie Variablennamen, mit der Ausnahme, dass die drei oben aufgeführten Zeichen (# @ $) nicht erlaubt sind. Obwohl sie in einer Methodendefinition verwendet werden können, erfordert der Aufruf einer solchen Methode die Verwendung von eckigen Klammern. Zum Beispiel wäre meinObjekt["@home"]() im Gegensatz zu meinObjekt.@home() gültig.

Variablenreferenzen vs. Werte

Variablen haben gewisse Ausprägungen, die die Grenze zwischen einer Variable und ihrem Wert verwischen, aber 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 genutzt 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. Diese Tatsache erlaubt es, dass die Funktion das Objekt modifizieren kann, aber sie verhindert auch, dass die Funktion die Variable, die der Funktionsaufrufer übergeben hat, modifizieren kann, weil die Funktion nicht die Variable, sondern nur eine Referenz zum Objekt hat.

Objektreferenzen

Ein Skript interagiert mit einem Objekt nicht direkt, sondern via Referenz zum Objekt. Wenn Sie ein Objekt erstellen, wird das Objekt an einem Ort erstellt, den Sie nicht kontrollieren können, und eine Referenz an Sie ü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; das heißt, dass es weder möglich noch lohnenswert ist, ein Objekt explizit zu löschen.

Ref1 := Object()  ; Erstellt ein Objekt und speichert die erste Referenz
Ref2 := Ref1      ; Erstellt eine neue Referenz zum selben Objekt
Ref1 := ""        ; Gibt die erste Referenz frei
Ref2 := ""        ; Gibt die zweite Referenz frei; Objekt wird gelöscht

Wenn das schwer zu verstehen ist, sollten Sie versuchen, 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 mehr Schlüssel erhalten und sie benutzen, um die Wohnung zu betreten, aber sobald Sie vorhaben, die Wohnung endgültig zu verlassen, müssen Sie alle Schlüssel an den Vermieter zurückgeben. In der Regel wird eine Wohnung nicht gelöscht, aber vielleicht muss die Hausverwaltung jemanden beauftragen, der Ihren zurückgelassenen Müll wegräumt; genauso wie der Fall, dass die Werte, die Sie in ein Objekt gespeichert haben, freigegeben werden, wenn das Objekt gelöscht wird.