Funktionen

Inhaltsverzeichnis

Einführung und einfache Beispiele

Eine Funktion ist so etwas Ähnliches wie eine Subroutine (GoSub), allerdings mit dem Unterschied, dass eine Funktion zusätzlich mit Parametern (Eingabewerten) aufgerufen werden kann. Eine Funktion kann außerdem einen Wert direkt an ihren Aufrufer zurückgeben. Das folgende Beispiel ist eine einfache Funktion, die zwei Zahlen akzeptiert und ihre Summe zurückgibt:

Addieren(x, y)
{
    return x + y   ; "Return" erwartet einen Ausdruck.
}

So etwas nennt man auch eine Funktionsdefinition, weil es eine Funktion mit dem Namen "Addieren" erstellt (nicht Groß-/Kleinschreibung-sensitiv) und festlegt, dass jeder, der sie aufruft, genau zwei Parameter (x und y) bereitstellen muss. Um die Funktion aufzurufen, können Sie das Ergebnis der Funktion einer Variable mithilfe des Doppelpunkt-Gleich-Operators (:=) zuweisen. Zum Beispiel:

Var := Addieren(2, 3)  ; Speichert die Zahl 5 in Var.

Man kann eine Funktion auch aufrufen, ohne ihren Rückgabewert speichern zu müssen:

Addieren(2, 3)

In diesem Fall aber wird der Rückgabewert der Funktion verworfen; diese Art von Aufruf ist nur sinnvoll, wenn die Funktion mehr als nur einen Rückgabewert zurückgibt.

Da ein Funktionsaufruf ein Ausdruck ist, dürfen die Namen der Variablen innerhalb ihrer Parameterliste nicht von Prozentzeichen umschlossen sein. Direkt geschriebene Zeichenketten müssen hingegen in doppelte Anführungszeichen gesetzt werden. Zum Beispiel:

if InStr(MeineVar, "Fuchs")
    MsgBox Die Variable MeineVar enthält das Wort Fuchs.

Es ist möglich, Funktionen innerhalb der Parameter eines Befehls aufzurufen (außer in EingabeVar- und AusgabeVar-Parametern, wie die von StringLen). Parameter, die keine Ausdrücke unterstützen, können mit dem Präfix "% " einen Ausdruck erzwingen. Zum Beispiel:

MsgBox % "Das Ergebnis ist: " . Addieren(3, 2)

Wenn dieses Prozentzeichen in einem Parameter angewendet wird, der Ausdrücke bereits unterstützt, wird es einfach ignoriert.

Parameter

Die Parameter einer Funktion werden in die runden Klammern rechts neben dem Funktionsnamen eingefügt (zwischen dem Namen und der runden Startklammer sind keine Leerzeichen erlaubt). Wenn die Funktion keine Parameter akzeptiert, können die runden Klammern leer gelassen werden; zum Beispiel: ErmittleAktuellenZeitstempel().

ByRef-Parameter: Innerhalb der Funktion werden Parameter grundsätzlich wie lokale Variablen behandelt, es sei denn, sie werden wie im folgenden Beispiel als ByRef-Parameter definiert:

Tauschen(ByRef Links, ByRef Rechts)
{
    temp := Links
    Links := Rechts
    Rechts := temp
}

Das ByRef oben macht den Parameter zu einem Pseudonym für die Variable, die der Aufrufer übergeben hat. Das heißt, dass der Parameter und die Variable des Aufrufers auf den gleichen Inhalt im Speicher verweisen. Auf diese Weise kann die Tauschen-Funktion die Variablen des Aufrufers ändern, indem sie den Inhalt der Links-Variable in die Rechts-Variable verschiebt, und umgekehrt.

Würde man ByRef hingegen nicht verwenden, wären Links und Rechts nur Kopien der Variablen des Aufrufers - die Tauschen-Funktion hätte keine externe Auswirkung.

ByRef kann als Ergänzung zu Return verwendet werden, um mehr als einen Wert zurückzugeben. Um das zu erreichen, definieren Sie eine Funktion mit ByRef-Parametern, damit der Aufrufer Variablen übergeben kann (üblicherweise leer), in der die Funktion einen Wert speichern kann.

Die Übergabe langer Zeichenketten an eine Funktion via ByRef ist leistungsfähiger und verhindert, dass die Zeichenketten doppelten Speicherplatz verbrauchen, weil von ihnen eine Kopie erstellt werden muss. Auch die Rückgabe von langen Zeichenketten an den Aufrufer via ByRef ist in der Regel performanter als so etwas wie Return LangeZeichenkette.

[AHK_L 60+]: Übergibt man eine schreibgeschützte Variable an einen ByRef-Parameter, verhält sich die Funktion so, als wäre das Schlüsselwort "ByRef" nicht vorhanden. Tauschen(A_Index, i) beispielsweise speichert den Wert von A_Index in i, allerdings wird der Wert von Links wieder verworfen, wenn die Tauschen-Funktion fertig ist.

[v1.1.01+]: Mit der IsByRef()-Funktion kann festgestellt werden, ob der Aufrufer eine Variable für einen bestimmten ByRef-Parameter bereitgestellt hat.

Bekannte Einschränkungen:

Optionale Parameter

Bei der Definition einer Funktion können ein oder mehrere Parameter als optional gekennzeichnet werden. Um das zu tun, müssen Sie := (in [v1.1.09] oder höher) oder = anfügen, gefolgt vom Standardwert des Parameters, der Folgendes sein kann: True, False, ein direkt geschriebener Integer, eine direkt geschriebene Floating-Point-Zahl oder eine direkt geschriebene, in Anführungszeichen gesetzte Zeichenkette wie "fox" oder "" (Zeichenketten unterstützen vor [v1.0.46.13] nur "").

Die Verwendung von = (ohne Doppelpunkt) ist aus Gründen der Abwärtskompatibilität erlaubt, aber nicht empfohlen, da es in AutoHotkey v2 nicht mehr zugelassen ist. Unabhängig davon, welcher Operator verwendet wird, müssen Standardwerte, die Zeichenketten sind, immer in Anführungszeichen gesetzt werden.

Die folgende Funktion hat einen Z-Parameter, der als optional gekennzeichnet ist:

Addieren(X, Y, Z:=0) {
    return X + Y + Z
}

Ruft man die Funktion mit drei Parametern auf, wird der Standardwert von Z ignoriert. Ruft man aber die Funktion nur mit zwei Parametern auf, bekommt die Z-Variable automatisch eine 0 zugewiesen.

Es ist nicht möglich, optionale Parameter in der Mitte der Parameterliste zu platzieren. Mit anderen Worten: Alle Parameter auf der rechten Seite des ersten optionalen Parameters müssen auch als optional markiert sein. [AHK_L 31+]: Optionale Parameter können in der Mitte der Parameterliste weggelassen werden, wenn die Funktion aufgerufen wird (siehe unten). In [v1.1.12+] gilt das auch für dynamische Funktionen und Methoden.

MeineFunk(1,, 3)
MeineFunk(X, Y:=2, Z:=0) {  ; Beachten Sie, dass Z in diesem Fall weiterhin optional sein muss.
    MsgBox %X%, %Y%, %Z%
}

[v1.0.46.13+]: ByRef-Parameter können auch einen Standardwert haben; zum Beispiel: MeineFunk(ByRef p1 = ""). Wenn die Funktion ohne diesen Parameter aufgerufen wird, wird eine lokale Variable mit dem angegebenen Standardwert erstellt; das heißt, dass die Funktion sich so verhalten wird, als wäre das Schlüsselwort "ByRef" nicht vorhanden.

Werte an den Aufrufer zurückgeben

Wie in der Einführung bereits erwähnt, kann eine Funktion einen Wert via Return an ihren Aufrufer zurückgeben.

Test := returnTest()
MsgBox % Test

returnTest() {
    return 123
}

Wenn Sie noch mehr Ergebnisse aus einer Funktion zurückgeben möchten, können Sie auch ByRef nutzen:

returnByRef(A,B,C)
MsgBox % A "," B "," C

returnByRef(ByRef val1, ByRef val2, ByRef val3)
{
    val1 := "A"
    val2 := 100
    val3 := 1.1
    return
}

[v1.0.97+]: Mithilfe von Objekten und Arrays können mehrere Werte oder sogar benannte Werte zurückgegeben werden:

Test1 := returnArray1()
MsgBox % Test1[1] "," Test1[2]

Test2 := returnArray2()
MsgBox % Test2[1] "," Test2[2]

Test3 := returnObject()
MsgBox % Test3.id "," Test3.val

returnArray1() {
    Test := [123,"ABC"]
    return Test
}

returnArray2() {
    x := 456
    y := "EFG"
    return [x, y]
}

returnObject() {
    Test := {id: 789, val: "HIJ"}
    return Test
}

Variadische Funktionen [AHK_L 60+]

Es ist möglich, den letzten Parameter in einer Funktionsdefinition mit einem Sternchen zu versehen, um eine Funktion variadisch zu machen, oder anders gesagt, um sie eine variable Anzahl von Parametern akzeptieren zu lassen:

Verbinden(sep, params*) {
    for index,param in params
        str .= param . sep
    return SubStr(str, 1, -StrLen(sep))
}
MsgBox % Verbinden("`n", "eins", "zwei", "drei")

Wenn man eine variadische Funktion aufruft, werden alle überschüssigen Parameter in ein Objekt gespeichert, das im letzten Parameter der Funktion enthalten ist. Der erste überschüssige Parameter ist params[1], der Zweite ist params[2] und so weiter. Dieses Objekt kann wie alle normalen Objekte params.MaxIndex() verwenden, um den höchsten numerischen Index zu ermitteln (in diesem Fall die Parameteranzahl). Wenn aber keine Parameter vorhanden sind, gibt MaxIndex eine leere Zeichenkette zurück.

Hinweise:

Variadische Funktionsaufrufe

Variadische Funktionen können mithilfe eines Arrays eine variable Anzahl von Parametern akzeptieren, während variadische Funktionsaufrufe verwendet werden können, um eine variable Anzahl von Parametern an eine beliebige Funktion mithilfe derselben Syntax zu übergeben:

TeilZketten := ["eins", "zwei", "drei"]
MsgBox % Verbinden("`n", TeilZketten*)

Hinweise:

Bekannte Einschränkungen:

Lokale und globale Variablen

Lokale Variablen

Lokale Variablen sind funktionsspezifisch und nur innerhalb dieser Funktion sichtbar. Folglich kann eine lokale Variable, die denselben Namen hat wie eine globale Variable, etwas anderes als die globale Variable enthalten. Verschiedene Funktionen können bedenkenlos die gleichen Variablennamen benutzen.

Alle lokalen Variablen, die nicht statisch sind, werden automatisch freigegeben (leer gemacht), wenn die Funktion ihr Ende erreicht hat.

Interne Variablen wie Clipboard, ErrorLevel und A_TimeIdle sind nie lokal (sie sind von überall aus erreichbar) und können nicht neu deklariert werden.

Funktionen sind standardmäßig im Assume-Local-Modus. Variablen, die innerhalb einer Assume-Local-Funktion zugegriffen oder erstellt werden, sind standardmäßig lokal, aber es gibt folgende Ausnahmen:

Siehe unten, wie das Standardverhalten überschrieben werden kann (indem man die Variable deklariert oder den Modus der Funktion ändert).

Force-Local-Modus [v1.1.27+]: Wenn die erste Zeile der Funktion das Wort "local" ist, werden alle Variablenreferenzen (auch dynamische) als lokal angesehen, es sei denn, sie werden innerhalb der Funktion als global deklariert. Im Gegensatz zum Standardmodus verhält sich der Force-Local-Modus wie folgt:

Globale Variablen

Um innerhalb einer Funktion auf eine vorhandene globale Variable zu verweisen (oder eine neue zu erstellen), deklarieren Sie die Variable als globale Variable, bevor Sie sie verwenden. Zum Beispiel:

InDateiLoggen(ZuLoggenderText)
{
    global LogDateiName  ; Diese globale Variable bekam bereits einen Wert außerhalb dieser Funktion zugewiesen.
    FileAppend, %ZuLoggenderText%`n, %LogDateiName%
}

Assume-Global-Modus: Muss eine Funktion viele globale Variablen erstellen oder auf sie zugreifen, kann die Funktion so definiert werden, dass sie all ihre Variablen (außer ihre Parameter) global behandelt. Dazu muss in der ersten Zeile entweder das Wort "global" stehen oder eine lokale Variable deklariert sein. Zum Beispiel:

StandardwerteSetzen()
{
    global  ; Kann weggelassen werden, wenn die erste Zeile so etwas wie "local MeineVar" ist.
    GlobaleVar := 33  ; Speichert 33 in eine globale Variable und erstellt sie, falls notwendig.
    local x, y:=0, z  ; Lokale Variablen müssen in diesem Modus deklariert werden, weil sie sonst global behandelt werden.
}

Dieser Assume-Global-Modus kann auch von einer Funktion verwendet werden, um ein globales Array zu erstellen - z. B. eine Schleife, die Werte in Array%A_Index% speichert.

Superglobale Variablen [v1.1.05+]: Geschieht eine globale Deklaration außerhalb einer Funktion, gilt sie standardmäßig für alle Funktionen (außer Force-Local-Funktionen). Dadurch wird verhindert, dass die Variablen in jeder Funktion neu deklariert werden müssen. Allerdings haben Funktionsparameter oder lokale Variablen, die denselben Namen haben wie globale Variablen, Vorrang vor globale Variablen. Variablen, die mit dem Schlüsselwort class erzeugt wurden, sind ebenfalls superglobal.

Statische Variablen

Obwohl statische Variablen immer indirekt lokal sind, unterscheiden sie sich von lokalen Variablen, weil ihre Werte zwischen den Funktionsaufrufen erhalten bleiben. Zum Beispiel:

InDateiLoggen(ZuLoggenderText)
{
    static GeloggteZeilen := 0
    GeloggteZeilen += 1  ; Behandelt einen Zähler lokal (der Wert bleibt zwischen den Funktionsaufrufen erhalten).
    global LogDateiName
    FileAppend, %GeloggteZeilen%: %ZuLoggenderText%`n, %LogDateiName%
}

Statische Initialisierungen: In den Versionen vor v1.0.46 enthielten alle statischen Variablen vorerst einen leeren Wert; um also zu erkennen, ob statische Variablen zum ersten Mal verwendet wurden, musste man überprüfen, ob sie leer waren. [v1.0.46+]: Es ist möglich, eine statische Variable bei ihrer Deklaration mit etwas anderes als "" zu initialisieren. Fügen Sie einfach auf der rechten Seite des Variablennamens den Operator := oder = und einen der folgenden Werte an: True, False, ein direkt geschriebener Integer, eine direkt geschriebene Floating-Point-Zahl oder eine direkt geschriebene, in Anführungszeichen gesetzte Zeichenkette wie "fox". Zum Beispiel: static X:=0, Y:="fox". Jede statische Variable wird nur einmal initialisiert (bevor das Skript seine Ausführung beginnt).

[AHK_L 58+]: Static Var := Ausdruck wird unterstützt. Alle derartigen Ausdrücke werden unmittelbar vor dem automatischen Ausführungsbereich ausgewertet - in der Reihenfolge, wie sie im Skript vorkommen.

Assume-Static-Modus [v1.0.48+]: Eine Funktion kann so definiert werden, dass sie all ihre Variablen (außer ihre Parameter) statisch behandelt. Dazu muss in der ersten Zeile das Wort "static" stehen. Zum Beispiel:

VomStatischenArrayAbrufen(ElementNummer)
{
    static
    static ErsterAufruf := true  ; Die Initialisierung einer statischen Deklaration wird nur einmal ausgeführt (beim Start).
    if ErsterAufruf  ; Erstellt ein statisches Array beim ersten Aufruf, aber nicht mehr danach.
    {
        ErsterAufruf := false
        Loop 10
            StatischesArray%A_Index% := "Wert #" . A_Index
    }
    return StatischesArray%ElementNummer%
}

Im Assume-Static-Modus muss jede Variable, die nicht statisch sein soll, als lokal oder global deklariert werden (mit den gleichen Ausnahmen wie beim Assume-Local-Modus, sofern der Force-Local-Modus nicht auch noch aktiv ist).

[v1.1.27+]: Der Force-Local-Modus kann mit dem Assume-Static-Modus kombiniert werden, indem man local und dann static angibt, wie unten gezeigt. Dies ermöglicht es der Funktion, Force-Local-Regeln zu verwenden, aber standardmäßig Variablen als statische Variablen zu erstellen.

global MeineVar := "Das ist global"
ForceStaticDemonstrieren()

ForceStaticDemonstrieren()
{
    local
    static
    MeineVar := "Dies ist statisch"
    ListVars
    MsgBox
}

Mehr über lokale und globale Variablen

Mehrere Variablen können mithilfe eines Kommas auf derselben Zeile deklariert werden. Zum Beispiel:

global LogDateiName, MaxVersuche := 5
static GesamtVersuche := 0, VorherErgebnis

[v1.0.46+]: Es ist möglich, eine lokale oder globale Variable bei ihrer Deklaration zu initialisieren. Fügen Sie einfach auf der rechten Seite des Variablennamens den Operator := oder = und einen beliebigen Ausdruck an (der =-Operator verhält sich in Deklarationen genauso wie :=). Im Gegensatz zu statischen Initialisierungen werden die Initialisierungen von lokalen oder globalen Variablen bei jedem Funktionsaufruf ausgeführt, aber nur, wenn der Kontrollfluss sie tatsächlich erreicht. Eine Zeile wie local x := 0 hätte also den gleichen Effekt wie, als würde man zwei einzelne Zeilen schreiben: local x, gefolgt von x := 0.

Da die Wörter local, global und static unmittelbar beim Starten des Skripts verarbeitet werden, kann eine Variable nicht mithilfe einer IF-Anweisung deklariert werden. Mit anderen Worten: Eine Deklaration innerhalb eines IF- oder ELSE-Blocks wirkt sich auf alle Zeilen zwischen der Deklaration und der geschweiften Endklammer der Funktion aus. Beachten Sie zudem, dass es zurzeit nicht möglich ist, eine dynamische Variable zu deklarieren, wie z. B. global Array%i%.

Befehle, die Pseudo-Arrays erzeugen (z. B. StringSplit), erstellen standardmäßig lokale Variablen, solange der Assume-Global-Modus nicht aktiv ist oder das erste Pseudo-Array-Element als lokale Variable deklariert wurde (dies trifft auch zu, wenn einer der Funktionsparameter übergeben wurde -- sogar wenn es ein ByRef-Parameter ist -- weil Parameter immer lokal sind). Umgekehrt wird ein globales Array erzeugt, wenn das erste Element global deklariert wurde. Beachten Sie, dass hierbei der unten erwähnte Häufige Anlass zu Verwirrung berücksichtigt werden muss. Das erste erzeugte Element von StringSplit ist ArrayName0. Das erste erzeugte Element von anderen array-erstellenden Befehlen wie WinGet List ist ArrayName (also ohne Nummer). [v1.1.27+]: Wenn der Force-Local-Modus aktiv ist, folgen diese Befehle den gleichen Regeln wie normale Variablenreferenzen; das heißt, dass jedes Pseudo-Array-Element, das nicht als global deklariert ist, lokal sein wird, auch wenn andere Elemente als global deklariert sind.

Innerhalb einer Funktion (sofern der Force-Local-Modus nicht aktiv ist) wird jede dynamische Variablenreferenz wie Array%i% in eine lokale Variable aufgelöst, es sei denn, es existiert keine Variable mit diesem Namen, dann wird eine globale Variable verwendet, sofern vorhanden. Wenn weder eine lokale noch globale Variable vorhanden ist und die Nutzung erfordert, dass die Variable erstellt sein muss, wird sie als lokale Variable erstellt, solange der Assume-Global-Modus nicht aktiv ist. Eine Funktion kann ein globales Array demzufolge nur erstellen (z. B. via Array%i% := A_Index), wenn der Assume-Global-Modus aktiv ist.

Häufiger Anlass zu Verwirrung: Jede nicht-dynamische Referenz zu einer Variable bewirkt, dass diese Variable beim Starten des Skripts erstellt wird. Außerhalb einer Funktion bewirkt eine Anweisung wie MsgBox %Array1% beispielsweise, dass eine globale Variable namens Array1 beim Starten des Skripts erstellt wird. Innerhalb einer Funktion bewirkt eine Anweisung wie MsgBox %Array1% hingegen, dass eine funktionsspezifische lokale Variable namens Array1 beim Starten des Skripts erstellt wird (solange der Assume-Global-Modus nicht aktiv ist), auch dann, wenn Array und Array0 als global deklariert sind.

Funktionen dynamisch aufrufen

[v1.0.47.06+]: Eine Funktion (auch eine interne Funktion) kann dynamisch via Prozentzeichen aufgerufen werden. %Var%(x, "Fuchs") beispielsweise wird aufgerufen, wenn Var den Namen einer gültigen Funktion enthält. Funk%A_Index%() kann hingegen Funk1(), Funk2() und so weiter aufrufen, je nachdem, welcher Wert in A_Index aktuell enthalten ist.

[v1.1.07.00+]: Var in %Var%() kann einen Funktionsnamen oder ein Funktionsobjekt enthalten. Falls die Funktion nicht existiert, wird stattdessen die __Call-Metafunktion des Standardbasisobjekts aufgerufen.

Wenn die Funktion aus einem der folgenden Gründe nicht aufgerufen werden kann, stoppt die Auswertung des Ausdrucks, der den Aufruf enthält, vorzeitig ohne Fehlermeldung, was zu inkonsistenten Ergebnissen führen kann:

Beachten Sie, dass ein dynamischer Aufruf etwas langsamer ist als ein normaler Aufruf, weil normale Aufrufe aufgelöst (nachgeschlagen) werden, bevor das Skript seine Ausführung beginnt.

Boolesche Kurzschlussauswertung

AND, OR und der ternäre Operator innerhalb eines Ausdrucks reduzieren die Auswertung auf ein Minimum, um die Leistung zu erhöhen (egal ob Funktionsaufrufe vorhanden sind oder nicht). Beim Kurzschließen werden nur Bereiche des Ausdrucks ausgewertet, die Einfluss auf das Endergebnis haben. Im folgenden Beispiel wird gezeigt, wie genau das abläuft:

if (FarbeName != "" AND not FindeFarbe(FarbeName))
    MsgBox %FarbeName% konnte nicht gefunden werden.

Wenn die FarbeName-Variable leer sein sollte, wird die FindeFarbe()-Funktion nie aufgerufen, weil die linke Seite von AND als falsch gewertet wird, wodurch die rechte Seite nicht mehr in der Lage wäre, das Endergebnis auf wahr zu bringen.

Dieses Verhalten führt dazu, dass die Nebeneffekte einer Funktion (wie das Ändern des Inhalts einer globalen Variable) nie auftreten werden, wenn diese Funktion auf der rechten Seite von AND oder OR aufgerufen wird.

Beachten Sie außerdem, dass die Kurzschlussauswertung verschachtelte ANDs und ORs stufenweise abarbeitet. Wenn FarbeName z. B. im folgenden Ausdruck leer ist, wird nur der Vergleich ganz links durchgeführt, weil die linke Seite dann ausreichen würde, um das Endergebnis zweifelsfrei zu bestimmen:

if (FarbeName = "" OR FindeFarbe(FarbeName, Region1) OR FindeFarbe(FarbeName, Region2))
    break   ; Nichts zu durchsuchen oder Übereinstimmung gefunden.

Wie die Beispiele oben zeigen, sollten umfangreiche (zeitaufwendige) Funktionen in der Regel auf der rechten Seite von AND oder OR aufgerufen werden, um die Leistung zu erhöhen. Diese Technik kann auch genutzt werden, um das Aufrufen einer Funktion zu verhindern, wenn ihr ein Wert übergeben wurde, den sie für unpassend hält (z. B. eine leere Zeichenkette).

[v1.0.46+]: Der ternäre Bedingungsoperator (?:) wendet auch die Kurzschlussauswertung an, indem er nur die gewinnende Abzweigung auswertet.

Subroutinen in einer Funktion nutzen

Eine Funktion kann Subroutinen, aber keine Definitionen von anderen Funktionen enthalten. Sie können wie alle Subroutinen via GoSub gestartet und via Return beendet werden (in diesem Fall gilt das Return nicht für die Funktion, sondern für das GoSub).

Bekannte Einschränkung: Momentan darf der Name jeder Subroutine (Label) nur einmal im ganzen Skript vorkommen. Das Programm wird Sie benachrichtigen, wenn ein Label doppelt vorhanden ist.

Wenn eine Funktion GoSub verwendet, um zu einer öffentlichen Subroutine zu springen (also eine, die außerhalb der geschweiften Funktionsklammern zu finden ist), sind alle externen Variablen global und die lokalen Variablen der Funktion erst wieder zugänglich, wenn die Subroutine ihr Ende erreicht hat. Allerdings wird A_ThisFunc weiterhin den Namen der Funktion enthalten.

Ein Goto kann nicht verwendet werden, um innerhalb einer Funktion zu einer externen Subroutine zu springen, allerdings kann eine Funktion via Gosub zu einer externen Subroutine springen und von dort aus ein Goto durchführen.

Ein Goto ist trotz seines schlechten Rufes zum Beispiel nützlich, um innerhalb einer Funktion auf eine andere Position zu springen. Dies kann dazu beitragen, komplexe Funktionen zu vereinfachen, die mehrere Returns haben und vor einem Return aufgeräumt werden müssen.

Eine Funktion kann Subroutinen enthalten, die extern aufgerufen werden, wie z. B. Timer, g-Labels und Menüpunkte. Dies ist eine übliche Vorgehensweise, um die Subroutinen in einer separaten Datei für #Include zusammenzufassen. Dadurch wird verhindert, dass der automatische Ausführungsbereich des Skripts gestört wird. Allerdings gelten folgende Einschränkungen:

Return, Exit und allgemeine Bemerkungen

Wenn der Ausführungsablauf die geschweifte Endklammer der Funktion vor einem Return erreicht hat, endet die Funktion und gibt eine leere Zeichenkette zurück. Es wird auch ein leerer Wert zurückgegeben, wenn die Funktion den Parameter von Return explizit weglässt.

Wenn eine Funktion den Exit-Befehl zum Terminieren des aktuellen Threads verwendet, erhält ihr Aufrufer überhaupt keinen Rückgabewert. Das Var in Var := Addieren(2, 3) bliebe beispielsweise unverändert, wenn Addieren() via Exit beendet wird. Das gleiche passiert, wenn die Funktion einen Laufzeitfehler verursacht, wie z. B. das Ausführen einer nicht-existierenden Datei (nur wenn UseErrorLevel nicht aktiv ist).

Eine Funktion kann den Wert von ErrorLevel verändern, um einen leicht zu merkenden zusätzlichen Wert zurückzugeben.

Um eine Funktion mit einem oder mehreren leeren Werten (leeren Zeichenketten) aufzurufen, verwenden Sie zwei aufeinanderfolgende Anführungszeichen. Zum Beispiel: FindeFarbe(FarbeName, "").

Da das Aufrufen einer Funktion keinen neuen Thread startet, werden Änderungen an Einstellungen wie SendMode und SetTitleMatchMode auch für den Aufrufer wirksam.

Der Aufrufer kann nicht-existierende Variablen oder Array-Elemente an eine Funktion übergeben. Dies ist nützlich, wenn die Funktion den entsprechenden Parameter als ByRef erwartet. Ruft man beispielsweise ErmittleNächsteZeile(LeeresArray%i%) auf, wird die Variable LeeresArray%i% automatisch als lokale oder globale Variable erstellt (abhängig davon, ob der Aufrufer sich in einer Funktion befindet und ob der Assume-Global-Modus wirksam ist).

ListVars kann, wenn es in einer Funktion verwendet wird, die Namen und Inhalte von lokalen Variablen anzeigen. Solche Informationen können helfen, ein Skript zu debuggen (Fehler zu finden und zu beseitigen).

Stil- und Namenskonventionen

Bei komplexen Funktionen kann es hilfreich sein, die speziellen Variablen mit eindeutigen Präfixen zu versehen, um die Übersichtlichkeit und Wartbarkeit des Skripts zu erhöhen. Die Namen der Parameter einer Funktion können beispielsweise mit "p" oder "p_" beginnen, damit die Parameter auf den ersten Blick leicht zu erkennen sind, besonders um die Übersicht zu bewahren, wenn eine Funktion mehrere Dutzend lokale Variablen enthält. Ebenso kann das Präfix "r" oder "r_" für ByRef-Parameter und "s" oder "s_" für statische Variablen verwendet werden.

Der One True Brace Style (OTB) kann je nach Bedarf angewendet werden, um Funktionen zu definieren. Zum Beispiel:

Addieren(x, y) {
    return x + y
}

Skripte mittels #Include auf die gleichen Funktionen zugreifen lassen

Die #Include-Direktive kann verwendet werden (auch am Anfang eines Skripts), um Funktionen aus einer externen Datei zu laden.

Erklärung: Wenn der Ausführungsablauf des Skripts eine Funktionsdefinition erreicht, wird sie übersprungen (dies passiert sofort) und die Ausführung bei der Zeile nach der geschweiften Endklammer fortgesetzt. Die Ausführung kann demzufolge nie in eine Funktionsdefinition geraten. Außerdem haben eine oder mehrere Funktionsdefinitionen ganz oben in einem Skript keinen Einfluss auf den automatischen Ausführungsbereich.

Funktionsbibliotheken: Standard- und Benutzerbibliothek [v1.0.47+]

Ein Skript kann eine Funktion in einer externen Datei aufrufen, ohne #Include verwenden zu müssen. Damit dies funktioniert, muss eine Datei, die den gleichen Namen hat wie die Funktion, in einem der folgenden Bibliotheksverzeichnisse vorkommen:

%A_ScriptDir%\Lib\  ; Lokale Bibliothek - benötigt [AHK_L 42+].
%A_MyDocuments%\AutoHotkey\Lib\  ; Benutzerbibliothek.
Verzeichnis-der-aktuell-laufenden-AutoHotkey.exe\Lib\  ; Standardbibliothek.

Wenn ein Skript beispielsweise die nicht-existierende Funktion MeineFunk() aufruft, durchsucht das Programm die Benutzerbibliothek nach einer Datei namens "MeineFunk.ahk". Wenn sie dort nicht ist, wird die Standardbibliothek durchsucht. Wenn sie dort auch nicht gefunden wurde und enthält der Funktionsname einen Unterstrich (z. B. MeinPräfix_MeineFunk), durchsucht das Programm beide Bibliotheken nach einer Datei namens MeinPräfix.ahk und lädt sie, falls sie existiert. Wenn MeinPräfix.ahk geladen wurde, sind sowohl die Funktion MeinPräfix_MeineFunk als auch andere verwandte Funktionen, deren Namen mit MeinPräfix_ beginnen, zugänglich.

[AHK_L 42+]: Die lokale Bibliothek wurde implementiert. Sie wird zuerst durchsucht, um eine Funktion zu finden.

Nur ein direkter Funktionsaufruf wie MeineFunk() bewirkt, dass eine Bibliothek automatisch eingebunden wird. Wenn die Funktion nur dynamisch oder indirekt aufgerufen wird, z. B. via Timer oder GUI-Ereignis, muss die Bibliothek explizit in das Skript eingebunden werden. Zum Beispiel: #Include <MeineFunk>

Obwohl eine Bibliotheksdatei in der Regel nur eine einzelne Funktion mit demselben Namen wie die Datei enthält, kann sie auch private Funktionen und Subroutinen enthalten, die nur von ihr aufgerufen werden. Allerdings sollten solche Funktionen eindeutige Namen haben, weil sie im globalen Namensraum sind; das heißt, dass sie von überall im Skript aufgerufen werden können.

Wenn eine Bibliotheksdatei #Include ausführt, verwendet #Include als Arbeitsverzeichnis das Verzeichnis der Bibliotheksdatei. Dies kann genutzt werden, um eine Weiterleitung zu einer größeren Bibliotheksdatei zu erschaffen, die diese Funktion und andere damit verbundene Funktionen enthält.

Der Skript-Compiler (ahk2exe) unterstützt auch Bibliotheksfunktionen. Der Compiler setzt aber voraus, dass eine Kopie von AutoHotkey.exe im übergeordneten Verzeichnis des Compiler-Verzeichnisses vorhanden ist (was normalerweise der Fall ist). Wenn der Compiler dort keine AutoHotkey.exe findet, funktioniert er immer noch, aber die Bibliotheksfunktionen werden nicht mehr automatisch eingebunden.

Funktionen, die aus einer Bibliothek eingebunden werden, sind genauso leistungsfähig wie normale Funktionen, weil sie geladen werden, bevor das Skript seine Ausführung beginnt.

Interne Funktionen

Alle optionalen Parameter am Ende der Parameterliste einer internen Funktion können komplett weggelassen werden. WinExist("Unbenannt - Editor") ist zum Beispiel gültig, weil die anderen drei Parameter als leere Werte behandelt werden.

Eine interne Funktion gilt als überschrieben, wenn im Skript eine Funktion mit demselben Namen definiert ist. Zum Beispiel könnte man anstelle der normalen WinExist()-Funktion eine selbstdefinierte Funktion verwenden. Allerdings kann danach die originale Funktion nicht mehr aufgerufen werden.

Externe Funktionen, die sich in DLL-Dateien befinden, können via DllCall() aufgerufen werden.

Um weitere Informationen über eine bestimmte interne Funktion zu erfahren, klicken Sie einfach auf den entsprechenden Namen.

Häufig verwendete Funktionen

Funktion Beschreibung
FileExist Überprüft, ob eine Datei oder ein Ordner vorhanden ist, und gibt ihre/seine Attribute zurück.
GetKeyState Gibt True (1) zurück, wenn eine bestimmte Taste unten ist, und False (0), wenn sie oben ist.
InStr Sucht nach einem bestimmten Vorkommen einer Zeichenkette, beginnend von links oder rechts.
RegExMatch Überprüft, ob ein Suchmuster (regulärer Ausdruck) in einer Zeichenkette vorkommt.
RegExReplace Ersetzt ein oder mehr Vorkommen eines Suchmusters (regulärer Ausdruck) innerhalb einer Zeichenkette.
StrLen Ermittelt die Anzahl der Zeichen, die in einer Zeichenkette enthalten sind.
StrReplace Ersetzt Vorkommen einer bestimmten Teilzeichenkette mit einer neuen Zeichenkette.
StrSplit Teilt anhand bestimmter Trennzeichen eine Zeichenkette in mehrere Teilzeichenketten auf.
SubStr Ermittelt ein oder mehrere Zeichen von einer bestimmten Stelle innerhalb einer Zeichenkette.
WinActive Überprüft, ob ein bestimmtes Fenster aktiv ist, und gibt dessen HWND-Nummer (eindeutige ID) zurück.
WinExist Überprüft, ob ein bestimmtes Fenster existiert, und gibt die HWND-Nummer (eindeutige ID) des ersten gefundenen Fensters zurück.

Verschiedene Funktionen

Funktion Beschreibung
Asc Gibt einen numerischen Wert zurück, der den ersten Byte oder die erste UTF-16-Codeeinheit einer bestimmten Zeichenkette repräsentiert.
Chr Gibt eine Zeichenkette zurück (üblicherweise ein einzelnes Zeichen), deren Zeichencode mit einer bestimmten Nummer übereinstimmt.
DllCall Ruft eine Funktion aus einer DLL-Datei auf, wie z. B. eine API-Funktion von Windows.
Exception Erstellt ein Objekt, das genutzt werden kann, um eine benutzerdefinierte Ausnahme auszulösen.
FileOpen Öffnet eine Datei, um bestimmte Inhalte aus ihr zu lesen und/oder in diese zu schreiben.
Format Formatiert eine beliebige Anzahl von Eingabewerten auf Basis einer Formatzeichenkette.
Func Ruft eine Referenz zu einer bestimmten Funktion ab.
GetKeyName/VK/SC Ermittelt den Namen/Text, virtuellen Tastencode oder Scancode einer Taste.
Hotstring Erstellt, bearbeitet, aktiviert oder deaktiviert einen Hotstring, während das Skript läuft.
IL_XXX Funktionen zum Erstellen oder Löschen von ImageLists, oder um Symbole/Bilder in ImageLists einzufügen (für ListView- oder TreeView-Steuerelemente).
InputHook Erstellt ein Objekt, das zum Erfassen oder Abfangen von Tastatureingaben genutzt werden kann.
IsByRef Gibt eine Nummer ungleich 0 zurück, wenn ein bestimmter ByRef-Parameter eine Variable übergeben bekommen hat.
IsFunc Gibt eine Nummer ungleich 0 zurück, wenn eine bestimmte Funktion im Skript vorkommt.
IsLabel Gibt eine Nummer ungleich 0 zurück, wenn ein bestimmtes Label im Skript vorkommt.
IsObject Gibt eine Nummer ungleich 0 zurück, wenn ein bestimmter Wert ein Objekt ist.
IsSet Gibt eine Nummer ungleich 0 zurück, wenn eine bestimmte Variable einen Wert zugewiesen bekommen hat.
LoadPicture Lädt ein Bild aus einer Datei und gibt ein Bitmap- oder Symbol-Handle zurück.
LV_XXX Funktion zum Hinzufügen, Einfügen, Modifizieren oder Löschen von ListView-Zeilen/Spalten, oder zum Abrufen ihrer Daten.
NumGet Gibt eine binäre Nummer zurück, die auf einer bestimmten Adresse + Offset zu finden ist.
NumPut Speichert eine binäre Nummer auf eine bestimmte Adresse + Offset.
ObjAddRef / ObjRelease Erhöht oder verringert die Referenzanzahl eines Objekts um 1.
ObjBindMethod Erstellt ein BoundFunc-Objekt, das eine Methode des angegebenen Objekts aufruft.
ObjGetBase Ermittelt das Basisobjekt des Objekts.
ObjRawGet Ermittelt ein Schlüssel-Wert-Paar eines Objekts und umgeht dabei die Metafunktionen des Objekts.
ObjRawSet Speichert oder überschreibt ein Schlüssel-Wert-Paar in einem Objekt und umgeht dabei die Metafunktionen des Objekts.
ObjSetBase Setzt das Basisobjekt eines Objekts.
ObjXXX Funktionen, die äquivalent zu den internen Methoden eines Objekts sind, wie z. B. ObjInsertAt. In der Regel ist es besser, anstelle der Funktion die entsprechende Methode zu benutzen.
OnClipboardChange Registriert eine Funktion oder ein Funktionsobjekt, die bzw. das jedes Mal ausgeführt wird, wenn sich der Inhalt der Zwischenablage ändert.
OnError Bestimmt eine Funktion, die automatisch gestartet werden soll, wenn ein unbehandelter Fehler auftritt.
OnExit Bestimmt eine Funktion, die automatisch ausgeführt werden soll, wenn das Skript beendet wird.
OnMessage Überwacht eine Meldung/ein Ereignis.
Ord Gibt den Ordinalwert (numerischen Zeichencode) des ersten Zeichens in einer bestimmten Zeichenkette zurück.
SB_XXX Funktionen, mit denen Text/Symbolen in die Leiste eines StatusBar-Steuerelements eingefügt werden oder die Leiste in mehrere Segmente aufgeteilt werden.
StrGet Liest eine Zeichenkette auf einer Speicheradresse unter Beachtung des angegebenen Zeichensatzes.
StrPut Schreibt eine Zeichenkette auf eine Speicheradresse unter Beachtung des angegebenen Zeichensatzes.
RegisterCallback Erstellt eine Maschinencode-Adresse, die, wenn aufgerufen, den Aufruf an eine Funktion im Skript weiterleitet.
Trim / LTrim / RTrim Entfernt Zeichen vom Anfang und/oder Ende einer Zeichenkette.
TV_XXX Funktionen zum Hinzufügen, Modifizieren oder Löschen von TreeView-Elementen, oder zum Abrufen ihrer Daten.
VarSetCapacity Vergrößert die Aufnahmekapazität einer Variable oder gibt deren Speicher frei.
VerCompare Vergleicht zwei Versionszeichenketten.

Mathematik

Funktion Beschreibung
Abs Gibt den absoluten Wert einer bestimmten Zahl zurück.
Ceil Gibt eine bestimmte Zahl zurück, aufgerundet auf den nächsten Integer (ohne .00-Suffix).
Exp Gibt e zurück (ungefähr 2.71828182845905), potenziert mit N.
Floor Gibt eine bestimmte Zahl zurück, abgerundet auf den nächsten Integer (ohne .00-Suffix).
Log Gibt den Logarithmus (Basis 10) einer bestimmten Zahl zurück.
Ln Gibt den Logarithmus (Basis e) einer bestimmten Zahl zurück.
Max / Min Gibt den höchsten/niedrigsten Wert von einer oder mehreren Zahlen zurück.
Mod Gibt den Rest aus einer Division zweier Zahlen zurück.
Round Gibt eine bestimmte Zahl zurück, gerundet auf N Dezimalstellen.
Sqrt Gibt die Quadratwurzel einer bestimmten Zahl zurück.
Sin / Cos / Tan Gibt den trigonometrischen Sinus/Kosinus/Tangens einer bestimmten Zahl zurück.
ASin / ACos / ATan Gibt den Arkussinus/Arkuskosinus/Arkustangens als Bogenmaß zurück.

COM

Funktion Beschreibung
ComObjActive Ermittelt ein registriertes COM-Objekt.
ComObjArray Erstellt einen SafeArray, das für COM genutzt werden kann.
ComObjConnect Verbindet die Ereignisquellen eines COM-Objekts mit Funktionen, die ein bestimmtes Präfix haben.
ComObjCreate Erstellt ein COM-Objekt.
ComObject Erstellt ein Objekt, das in typisierter Form als Parameter oder Rückgabewert übergeben werden kann.
ComObjEnwrap / ComObjUnwrap Wrappt/entwrappt ein COM-Objekt.
ComObjError Aktiviert oder deaktiviert COM-spezifische Fehlermeldungen.
ComObjFlags Ermittelt oder ändert Flags, die das Verhalten eines COM-Wrapper-Objekts kontrollieren.
ComObjGet Gibt eine Referenz zu einem Objekt zurück, das von einer COM-Komponente zur Verfügung gestellt wurde.
ComObjMissing Erstellt ein Objekt für "fehlende Parameter", das an eine COM-Methode übergeben werden kann.
ComObjParameter Wrappt einen Wert und Typ zu einem Objekt, das einer COM-Methode als Parameter übergeben werden kann.
ComObjQuery Fordert ein Interface oder Service eines COM-Objekts an.
ComObjType Ruft Typinformationen eines COM-Objekts ab.
ComObjValue Ermittelt den Wert oder Pointer, der in einem COM-Wrapper-Objekt hinterlegt ist.

Sonstige Funktionen

Befehlsfunktionen von Polyethene: Bietet für jeden AutoHotkey-Befehl, der eine Ausgabevariable hat, eine aufrufbare Funktion. Diese Bibliothek kann via #Include in einem beliebigen Skript eingebunden werden.