Funktionen

Inhaltsverzeichnis

Einführung und einfache Beispiele

Eine Funktion ist prinzipiell das gleiche wie eine Subroutine (GoSub), außer dass sie Parameter (Eingabewerte) von ihrem Aufrufer entgegennehmen kann. Darüber hinaus kann eine Funktion optional einen Wert an den Aufrufer zurückgeben. Das folgende Beispiel zeigt, wie eine einfache Funktion zwei Zahlen entgegennimmt und deren 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 (Groß- und Kleinschreibung ist egal) und festlegt, dass jeder, der sie aufruft, genau zwei Parameter (x und y) bereitstellen muss. Um die Funktion aufzurufen, speichert man ihr Ergebnis mithilfe des Doppelpunkt-Gleich-Operators (:=) in eine Variable. 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 zurückgegebene Wert der Funktion verworfen; wenn die Funktion nur einen Rückgabewert erzeugen würde, wäre ihr Aufruf daher sinnlos.

Da ein Funktionsaufruf ein Ausdruck ist, sollten Variablennamen in ihrer Parameterliste nicht von Prozentzeichen umschlossen sein. Dagegen sollten literale Zeichenketten in Anführungszeichen gesetzt werden. Zum Beispiel:

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

Desweiteren kann man Funktionen innerhalb der Parameter eines Befehls aufrufen (außer in EingabeVar und AusgabeVar-Parametern, wie die von StringLen). Allerdings müssen Parameter, die keine Ausdrücke unterstützen, den "%"-Präfix wie folgt verwenden:

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

Das "%"-Präfix kann auch in Parametern verwendet werden, die bereits Ausdrücke unterstützen, aber es wird einfach ignoriert.

Parameter

Beim Definieren einer Funktion werden die Parameter neben dem Funktionsnamen in Klammern aufgelistet (Leerzeichen zwischen dem Namen und der öffnenden Klammer sind nicht erlaubt). Braucht die Funktion keine Parameter, können die Klammern leer gelassen werden; zum Beispiel: ErmittleAktuellenZeitstempel().

ByRef-Parameter: Innerhalb der Funktion werden Parameter grundsätzlich wie lokale Variablen behandelt, sofern sie nicht wie folgt als ByRef-Parameter definiert werden:

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

Das Benutzen von ByRef bewirkt, dass die angegebene Variable mit dem Parameter verbunden wird. Das heißt, dass der Parameter und die Variable des Aufrufers auf den gleichen Inhalt im Arbeitsspeicher 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.

Da Return nur einen einzigen Wert an den Funktionsaufrufer zurückgeben kann, ist ByRef gut dafür geeignet, zusätzliche Ergebnisse zurückzugeben. Bringe den Aufrufer einfach dazu, eine Variable zu übergeben (üblicherweise leer), in der die Funktion einen Wert speichern kann.

Beim Übergeben langer Zeichenketten an eine Funktion ist ByRef leistungsfähiger und außerdem platzsparend, weil keine Kopie der Zeichenkette gemacht werden muss. Ebenso ist ByRef, wenn man eine lange Zeichenkette an den Aufrufer zurücksenden will, leistungsfähiger als Return LangeZeichenkette.

[AHK_L 60+]: Übergibt man etwas anderes als eine veränderbare Variable an einen ByRef-Parameter, verhält sich die Funktion so, als wäre das Schlüsselwort "ByRef" nicht vorhanden. Zum Beispiel würde Tauschen(A_Index, i) den Wert von A_Index in i speichern, aber den gespeicherten Wert in Links verwerfen, sobald 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 einer Funktionsdefinition können die Parameter als optional gekennzeichnet werden. Dazu muss ein Gleichheitszeichen (oder seit v1.1.09 :=) und ein Standardwert angefügt werden. Im folgenden Beispiel ist der Z-Parameter als optional gekennzeichnet:

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

Seit v1.1.09 wird sowohl = als auch := unterstützt. Es wird empfohlen, die zweite Methode zu verwenden, um Widersprüche bei Ausdruckszuweisungen zu vermeiden und die Kompatibilität mit zukünftigen AutoHotkey-Versionen einzuhalten.

Übergibt der Aufrufer drei Parameter an die obere Funktion, wird der Standardwert von Z ignoriert. Wenn der Aufrufer aber nur zwei Parameter übergibt, wird in Z automatisch der Wert 0 gespeichert.

Es ist nicht möglich, alleinstehende optionale Parameter in der Mitte der Parameterliste zu verwenden. Das heißt, dass alle Parameter, die auf der rechten Seite des ersten optionalen Parameters vorkommen, auch als optional gekennzeichnet werden müssen. [AHK_L 31+]: Beim Aufrufen der Funktion können die optionale Parameter in der Mitte der Parameterliste weggelassen werden, wie unten gezeigt. Für dynamische Funktionsaufrufe und Methodenaufrufe wird v1.1.12+ benötigt.

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

Seit v1.0.46.13 unterstützen ByRef-Parameter auch Standardwerte; zum Beispiel: Funktion(ByRef p1 = ""). Jedes Mal, wenn der Aufrufer einen solchen Parameter weglässt, erstellt die Funktion eine lokale Variable, die den Standardwert enthält; das heißt, dass die Funktion sich so verhält, als würde das Schlüsselwort "ByRef" fehlen.

Als Standardwert eines Parameters sind folgende Werte zulässig: True, False, ein literaler Integer, eine literale Gleitkommazahl oder eine literale Zeichenkette wie "fox" oder "" (Zeichenketten unterstützen vor v1.0.46.13 nur "").

Rückgabewerte an den Aufrufer

Wie man bereits in der Einführung lesen konnte, kann eine Funktion dazu gebracht werden, einen Wert per Return an ihren Aufrufer zurückzugeben.

Test := returnTest()
MsgBox % Test

returnTest() {
  return 123
}

Wenn noch mehr Ergebnisse von einer Funktion zurückgegeben werden sollen, kann man auch ByRef verwenden:

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+]

Bei einer Funktionsdefinition kann ein Sternchen nach dem letzten Parameter angegeben werden, um die Funktion als variadisch zu kennzeichnen, so dass sie eine beliebige Anzahl an Parametern akzeptieren kann:

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

Ruft man eine variadische Funktion auf, sind überschüssige Parameter über ein Objekt zugreifbar, das im letzten Parameter der Funktion gespeichert ist. Der erste überschüssige Parameter ist params[1], der Zweite ist params[2] und so weiter. Wie bei anderen Standardobjekten auch, kann params.MaxIndex() verwendet werden, um den höchsten numerischen Index zu ermitteln (in diesem Fall die Parameteranzahl). Sind keine Parameter vorhanden, gibt MaxIndex jedoch eine leere Zeichenkette zurück.

Hinweise:

Variadische Funktionsaufrufe

Während variadische Funktionen eine beliebige Parameteranzahl akzeptieren können, kann ein Array mit Parametern an jede Funktion durch Anwenden der gleichen Syntax beim Funktionsaufruf übergeben werden:

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

Hinweise:

Bekannte Einschränkungen:

Lokale und globale Variablen

Lokale Variablen

Lokale Variablen gelten nur für eine einzige Funktion und sind nur in dieser sichtbar. Daher kann eine lokale Variable den gleichen Namen haben wie eine globale Variable, aber mit unterschiedlichem Inhalt. Separate Funktionen können ohne Probleme die gleichen Variablennamen benutzen.

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

Variablen, die innerhalb einer Funktion abgerufen oder erstellt werden, sind standardmäßig lokal, aber es gibt folgende Ausnahmen:

Zudem kann das Standardverhalten wie unten gezeigt überschrieben werden.

Globale Variablen

Um innerhalb einer Funktion auf eine vorhandene globale Variable zu verweisen (oder eine neue zu erstellen), deklariere die Variable als global, bevor man sie verwendet. Zum Beispiel:

LogZuDatei(TextZuLog)
{
    global LogDateiname  ; Dieser globalen Variable wurde bereits ein Wert außerhalb dieser Funktion zugewiesen.
    FileAppend, %TextZuLog%`n, %LogDateiname%
}

Global-behandelnder 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 die Deklaration einer lokalen Variable durchgeführt werden. Zum Beispiel:

SetzeStandardwerte()
{
    global  ; Kann weggelassen werden, wenn die erste Zeile so etwas wie "local MeineVar" ist.
    MeineGlobal := 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 global-behandelnde Modus kann auch von einer Funktion verwendet werden, um ein globales Array zu erstellen - wie bei einer Schleife, die Werte per Array%A_Index% zuweist.

Superglobale Variablen [v1.1.05+]: Geschieht eine globale Deklaration außerhalb einer Funktion, gilt sie standardmäßig für alle Funktionen. Dadurch wird verhindert, dass die Variablen jedes Mal in einer Funktion neu deklariert werden müssen. Funktionsparameter oder lokale Variablen mit gleichem Namen haben Vorrang vor der globalen Variable. Variablen, die mit dem Schlüsselwort class erzeugt wurden, sind auch superglobal.

Statische Variablen

Statische Variablen sind im Prinzip immer lokal. Der Unterschied ist aber, dass ihre Werte zwischen den Funktionsaufrufen erhalten bleiben. Zum Beispiel:

LogZuDatei(TextZuLog)
{
    static Zeilenanzahl = 0
    Zeilenanzahl += 1  ; Behandelt einen Zähler lokal (der Wert bleibt zwischen den Funktionsaufrufen erhalten).
    global LogDateiname
    FileAppend, %Zeilenanzahl%: %TextZuLog%`n, %LogDateiname%
}

Statische Initialisierungen: In den Versionen vor v1.0.46 enthielten alle statischen Variablen zu Beginn einen leeren Wert; das erstmalige Verwenden solcher Variablen konnte nur erkannt werden, wenn sie überprüft wurden, ob sie leer sind. Seit v1.0.46 können statische Variablen mit einem beliebigen Wert initialisiert werden (vorher war nur "" möglich), wenn := oder = gefolgt von einem folgenden Wert angefügt wird: True, False, ein literaler Integer, eine literale Gleitkommazahl oder eine literale 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. Solche Ausdrücke werden unmittelbar vor dem automatischen Ausführungsbereich ausgewertet - in der Reihenfolge, wie sie im Skript vorkommen.

Statisch-behandelnder 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:

ErmittleVomStatischenArray(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 statisch-behandelnden Modus muss jede Variable, die nicht statisch sein soll, als lokal oder global deklariert werden.

Mehr über lokale und globale Variablen

Es ist möglich, mehrere Variablen auf der gleichen Zeile zu deklarieren, wenn sie wie folgt durch Kommas getrennt werden:

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

Seit v1.0.46 kann eine lokale oder globale Variable auf der gleichen Zeile als Deklaration initialisiert werden, wenn ein := oder = gefolgt von einem Ausdruck angefügt wird (in Deklarationen verhält sich der Operator = wie :=). Im Gegensatz zu statischen Initialisierungen werden die Initialisierungen von lokalen oder globalen Variablen bei jedem Funktionsaufruf ausgeführt, sofern sie von der Ablaufsteuerung erreicht werden. Das heißt, dass eine Zeile wie local x = 0 den gleichen Effekt hat wie die zwei folgenden Zeilen: 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 bedingt per IF-Anweisung deklariert werden. Das heißt, dass eine Deklaration innerhalb eines IF- oder ELSE-Blocks bedingungslos für alle Zeilen zwischen der Deklaration und der schließenden Funktionsklammer wirksam wird. Beachte zudem, dass es zurzeit nicht möglich ist, eine dynamische Variable wie global Array%i% zu deklarieren.

Bei Befehlen, die Pseudo-Arrays erstellen (z. B. StringSplit), ist jede Variable im resultierenden Pseudo-Array lokal, solange der global-behandelnder Modus nicht aktiv ist oder das erste Pseudo-Array-Element als lokale Variable deklariert wurde (das gilt auch bei der Übergabe eines Funktionsparameters, selbst wenn dieser Parameter ein ByRef ist, da Parameter prinzipiell das gleiche sind wie lokale Variablen). Wurde das erste Element hingegen global deklariert, wird ein globales Array erstellt. Allerdings gilt die unten genannte Oft auftretende Verwechslungsgefahr auch in solchen Fällen. Das erste Element bei StringSplit ist ArrayName0. Bei anderen array-erstellenden Befehlen wie WinGet List ist das erste Element ArrayName (also ohne die Nummer).

Innerhalb einer Funktion wird jeder dynamische Variablenverweis wie Array%i% immer in eine lokale Variable aufgelöst. Wenn aber eine Variable mit diesem Namen nicht vorhanden ist, wird eine globale Variable verwendet, falls vorhanden. Wenn sie weder existiert noch bei ihrer Verwendung die Variable erstellt werden muss, wird sie als lokale Variable erstellt, solange der global-behandelnder Modus nicht aktiv ist. Daher kann eine Funktion ein globales Array nur manuell erstellen (z. B. mithilfe von Array%i% := A_Index), wenn in der Funktion der global-behandelnder Modus definiert wurde.

Oft auftretende Verwechslungsgefahr: Jeder nicht-dynamische Verweis auf eine Variable erstellt diese Variable in dem Moment, wo das Skript gestartet wird. Zum Beispiel: Außerhalb einer Funktion würde MsgBox %Array1% die Array1-Variable als globale Variable erstellen, in dem Moment, wo das Skript gestartet wird. Innerhalb einer Funktion würde MsgBox %Array1% die Array1-Variable als lokale Variable erstellen, in dem Moment, wo das Skript gestartet wird (solange der global-behandelnder Modus nicht aktiv ist), selbst wenn Array und Array0 als global deklariert sind.

Dynamisches Aufrufen einer Funktion

Seit v1.0.47.06 kann eine Funktion (auch eine Built-in-Funktion) mithilfe von Prozentzeichen dynamisch aufgerufen werden. Zum Beispiel würde %Var%(x, "Fuchs") die Funktion aufrufen, deren Name in Var enthalten ist. Ebenso würde Funktion%A_Index%() Funktion1(), Funktion2() und so weiter aufrufen, abhängig vom aktuellen Wert in A_Index.

Seit v1.1.07.00 kann Var in %Var%() einen Funktionsnamen oder ein Funktionsobjekt enthalten. Falls die Funktion nicht existiert, wird stattdessen die __Call-Meta-Funktion des Standard-base-Objekts aufgerufen.

Kann die Funktion aufgrund einer der unten genannten Gründe nicht aufgerufen werden, stoppt die Auswertung des Ausdrucks, der den Aufruf enthält, vorzeitig ohne Meldung, was zu widersprüchlichen Ergebnissen führen könnte:

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

Logische Kurzschlussauswertung

Sobald AND, OR und der ternäre Operator innerhalb eines Ausdrucks verwendet werden, schließen sie sich kurz, um die Performance 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 funktioniert:

if (FarbName <> "" AND not FindeFarbe(FarbName))
    MsgBox %FarbName% konnte nicht gefunden werden.

Wenn die FarbName-Variable leer sein sollte, wird die FindeFarbe()-Funktion niemals 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 Nebeneffekte von 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.

Beachte außerdem, dass die Kurzschlussauswertung verschachtelte ANDs und ORs stufenweise durchgeht. Im Ausdruck des folgenden Beispiels würde nur der Vergleich ganz links erfolgen, wann immer FarbName leer ist, weil die linke Seite dann ausreichen würde, um das Endergebnis mit Sicherheit zu bestimmen:

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

Wie die Beispiele oben zeigen, sollten lange (zeitaufwendige) Funktionen generell auf der rechten Seite von AND oder OR aufgerufen werden, um die Performance zu erhöhen. Diese Technik kann auch dazu genutzt werden, das Aufrufen einer Funktion zu verhindern, wenn ein ungeeigneter Wert (z. B. eine leere Zeichenkette) an einen ihrer Parameter übergeben wird.

Seit v1.0.46 erfolgt beim ternären Bedingungsoperator (?:) auch eine Kurzschließung durch Ignorieren der verlierenden Abzweigung.

Verwenden von Subroutinen innerhalb einer Funktion

Eine Funktion kann keine Definitionen von anderen Funktionen enthalten. Subroutinen sind aber möglich. Sie können, wie jede andere Subroutine auch, per GoSub gestartet und per 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. Beim Starten des Programms wird eine Fehlermeldung angezeigt, wenn Labels doppelt vorkommen.

Verwendet eine Funktion das GoSub, um zu einer öffentlichen Subroutine zu springen (die sich außerhalb der Funktionsklammern befindet), sind alle Variablen außerhalb global und die funktions-eigenen lokalen Variablen nicht abrufbar, bis die Subroutine ihr Return erreicht hat. Allerdings wird A_ThisFunc weiterhin den Namen der Funktion enthalten.

Das Goto kann nicht verwendet werden, um vom Inneren der Funktion nach außen zu springen. Allerdings kann eine Funktion per GoSub zu einer externen/öffentlichen Subroutine springen und von dort aus per Goto weiterspringen.

In der Regel sollte man auf Goto verzichten. Dieser Befehl kann aber innerhalb einer Funktion nützlich sein, wo man auf eine andere Position springen muss. Diese Methode kann helfen, komplexe Funktionen zu vereinfachen, die mehrere Rückgabepunkte haben, bei denen zuvor einige Säuberungsaktionen durchgeführt werden müssen.

Eine Funktion kann extern-aufrufende Subroutinen wie Timer, g-Label und Menüpunkte enthalten. Dies ist eine übliche Vorgehensweise, um sie in eine separate Datei zu packen und später via #Include bereitzustellen, so dass sie den automatischen Ausführungsbereich des Skripts nicht stören können. Allerdings gelten folgende Einschränkungen:

Return, Exit und allgemeine Bemerkungen

Erreicht der Ausführungsablauf innerhalb einer Funktion die schließende Funktionsklammer, ohne auf ein Return gestoßen zu sein, endet die Funktion und gibt ihren Aufrufer eine leere Zeichenkette zurück. Ein leerer Wert wird auch zurückgegeben, wenn der Parameter von Return explizit fehlt.

Wenn eine Funktion den aktuellen Thread mit dem Exit-Befehl terminiert, erhält ihr Aufrufer überhaupt keinen Rückgabewert. Zum Beispiel: Die Anweisung Var := Addieren(2, 3) würde Var unverändert belassen, wenn Add() per Exit beendet wird. Das gleiche passiert, wenn die Funktion einen Laufzeitfehler verursacht, wie das Ausführen einer nicht-existierenden Datei (nur wenn UseErrorLevel nicht aktiv ist).

Eine Funktion kann den Wert von ErrorLevel ändern, um einen zusätzlichen Wert zurückzugeben, der sich leicht merken lässt.

Um eine Funktion mit einer oder mehreren leeren Zeichenketten aufzurufen, verwende zwei Anführungszeichen wie folgt: FindeFarbe(FarbName, "").

Da das Aufrufen einer Funktion keinen neuen Thread startet, werden von der Funktion geänderten Einstellungen wie SendMode oder SetTitleMatchMode auch für den Aufrufer wirksam.

Der Aufrufer einer Funktion kann nicht-existierende Variablen oder Array-Elemente an ihr übergeben, was nützlich für Funktionen ist, die den entsprechenden Parameter als ByRef erwarten. 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 global-behandelnder Modus wirksam ist).

Wenn ListVars in einer Funktion verwendet wird, werden ihre lokalen Variablen und deren Inhalte angezeigt. Diese Sache kann dabei helfen, ein Skript zu debuggen.

Stil und Namenskonventionen

Man könnte komplexe Funktionen als besser lesbar und verwaltbar empfinden, wenn deren Variablen eindeutige Präfixe angefügt werden. Durch Hinzufügen von beispielsweise "p" oder "p_" am Anfang jeden Parameters ist seine besondere Art besser erkennbar, besonders wenn eine Funktion sehr viele lokale Variablen hat. Ebenso kann das Präfix "r" oder "r_" für ByRef-Parameter und "s" oder "s_" für statische Variablen verwendet werden.

Bei Bedarf kann der "One True Brace Style" verwendet 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 des Skripts), um Funktionen aus einer externen Datei zu laden.

Erklärung: Erreicht der Ausführungsablauf des Skripts eine Funktionsdefinition, wird er sie sofort überspringen und seine Ausführung bei der Zeile nach der schließenden Klammer fortsetzen. Daraus folgt, dass die Ausführung nie in eine Funktion geraten kann, oder dass das Vorhandensein von einer oder mehreren Funktionen am Anfang des Skripts den automatischen Ausführungsbereich beeinflussen könnten.

Libraries mit Funktionen: Standard- und Benutzer-Library [v1.0.47+]

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

%A_ScriptDir%\Lib\  ; Lokale Library - benötigt AHK_L 42+.
%A_MyDocuments%\AutoHotkey\Lib\  ; Benutzer-Library.
Pfad-zur-gerade-laufenden-AutoHotkey.exe\Lib\  ; Standard-Library.

Ruft ein Skript beispielsweise die nicht-existierende Funktion MeineFunktion() auf, sucht das Programm nach einer Datei namens "MeineFunktion.ahk" in der Benutzer-Library. Wenn sie dort nicht gefunden werden kann, wird die Standard-Library durchsucht. Ergibt die Suche weiterhin keine Treffer und enthält der Funktionsname einen Unterstrich (z. B. MeinPräfix_MeineFunktion), sucht das Programm in beiden Libraries nach einer Datei namens MeinPräfix.ahk und lädt sie, falls sie existiert. Auf diese Weise kann MeinPräfix.ahk sowohl die Funktion MeinPräfix_MeineFunktion als auch andere verwandte Funktionen enthalten, deren Namen mit MeinPräfix_ beginnen.

[AHK_L 42+]: Es kann nun die lokale Library verwendet werden, die durchsucht wird, bevor die Benutzer- und Standard-Library durchsucht werden.

Nur ein direkter Funktionsaufruf wie MeineFunk() kann eine Library automatisch einfügen lassen. Wenn die Funktion nur dynamisch oder indirekt aufgerufen wird, z. B. via Timer oder GUI-Ereignis, dann muss die Library explizit in das Skript eingefügt werden. Zum Beispiel: #Include <MeineFunk>

In der Regel enthält eine Library-Datei nur eine einzelne Funktion, die den gleichen Namen hat wie die Datei. Sie kann aber auch private Funktionen und Subroutinen enthalten, die nur von ihr aufgerufen werden. Die Namen solcher Funktionen sollten jedoch gut durchdacht sein, da sie weiterhin im globalen Namensraum zur Verfügung stehen; das heißt, dass sie von überall im Skript aufgerufen werden können.

Verwendet eine Library-Datei #Include, gilt als Arbeitsverzeichnis für #Include das Verzeichnis der Library-Datei. Der Vorteil davon ist, dass eine Weiterleitung zu einer größeren Library-Datei erstellt werden kann, die diese Funktion und andere dazugehörige Funktionen enthält.

Der Skript-Compiler (ahk2exe) unterstützt auch Library-Funktionen. Allerdings ist eine Kopie von AutoHotkey.exe im Verzeichnis oberhalb des Compiler-Verzeichnisses notwendig (was normalerweise der Fall ist). Wenn AutoHotkey.exe dort nicht vorhanden, wird der Compiler zwar weiterhin funktionieren, aber die Library-Funktionen werden nicht mehr automatisch eingefügt.

Funktionen, die auf diese Weise eingefügt werden, haben die gleiche Performance wie andere Funktionen, weil sie geladen werden, bevor das Skript seine Ausführung beginnt.

Built-in-Funktionen

Jeder optionale Parameter, der am Ende der Parameterliste einer Built-in-Funktion vorkommt, kann komplett weggelassen werden. Zum Beispiel könnte man WinExist("Unbenannt - Editor") angeben, weil die Funktion ihre anderen drei Parameter als leere Werte ansieht.

Eine Built-in-Funktion wird überschrieben, wenn das Skript seine eigene Funktion mit dem gleichen Namen definieren würde. 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 per DllCall() aufgerufen werden.

Klicke unten auf den Namen einer bestimmten Built-In-Funktion, um mehr über sie zu erfahren.

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 die angegebene Taste unten ist, und False (0), wenn sie oben ist.
InStr Sucht eine bestimmte Zeichenkette, beginnend von links oder rechts.
RegExMatch Überprüft, ob ein Muster (regulärer Ausdruck) in einer Zeichenkette vorkommt.
RegExReplace Ersetzt Vorkommen eines Musters (regulärer Ausdruck) innerhalb einer Zeichenkette.
StrLen Ermittelt die Anzahl an Zeichen, die sich in einer Zeichenkette befinden.
StrReplace Ersetzt Vorkommen der angegebenen Teilzeichenkette mit einer neuen Zeichenkette.
StrSplit Teilt eine Zeichenkette in mehreren Teilzeichenketten auf, basierend auf die angegebenen Trennzeichen.
SubStr Ermittelt ein oder mehrere Zeichen von der angegebenen Position innerhalb einer Zeichenkette.
WinActive Überprüft, ob das angegebene Fenster existiert und zurzeit aktiv (im Vordergrund) ist, und gibt dessen Eindeutige ID (HWND) zurück.
WinExist Überprüft, ob ein passendes Fenster existiert, und gibt die Eindeutige ID (HWND) des ersten passenden Fensters zurück.

Verschiedene Funktionen

Funktion Beschreibung
Asc Gibt den numerischen Wert des ersten Bytes oder der ersten UTF-16-Codeeinheit in der angegebenen Zeichenkette zurück.
Chr Gibt eine Zeichenkette zurück (üblicherweise ein einzelnes Zeichen), deren Zeichencode mit der angegebenen Nummer übereinstimmt.
DllCall Ruft eine Funktion innerhalb einer DLL-Datei auf, wie z. B. eine API-Funktion von Windows.
FileOpen Ermöglicht eine objektorientierte Dateibearbeitung.
Func Ermittelt einen Verweis auf die angegebene Funktion.
GetKeyName/VK/SC Ermittelt den Namen/Text, virtuellen Tastencode oder Scancode einer Taste.
IsByRef Gibt eine Nummer ungleich 0 zurück, wenn ein ByRef-Parameter einer Funktion mit einer Variable übergeben wurde.
IsFunc Gibt eine Nummer ungleich 0 zurück, wenn die angegebene Funktion im Skript vorkommt.
IsLabel Gibt eine Nummer ungleich 0 zurück, wenn das angegebene Label im Skript vorkommt.
IsObject Gibt eine Nummer ungleich 0 zurück, wenn der angegebene Wert ein Objekt ist.
ListView Funktion zum Hinzufügen, Einfügen, Modifizieren oder Löschen von ListView-Reihen/Spalten, oder zum Abrufen ihrer Daten.
NumGet Gibt eine binäre Nummer zurück, die auf der angegebenen Adresse + Offset zu finden ist.
NumPut Speichert eine binäre Nummer auf die angegebene Adresse + Offset.
OnMessage Überwacht eine Nachricht/ein Ereignis.
Ord Gibt den Ordinalwert (numerischen Zeichencode) des ersten Zeichens in der angegebenen Zeichenkette zurück.
StrGet Kopiert eine Zeichenkette aus einer Speicheradresse unter Beachtung des angegebenen Zeichensatzes.
StrPut Kopiert eine Zeichenkette auf eine Speicheradresse unter Beachtung des angegebenen Zeichensatzes.
RegisterCallback Erstellt eine Maschinencode-Adresse, die, wenn sie aufgerufen wird, den Aufruf an eine Funktion im Skript weiterleitet.
TreeView Funktionen zum Hinzufügen, Modifizieren oder Löschen von TreeView-Elementen, oder zum Abrufen ihrer Daten.
Trim Entfernt Zeichen vom Anfang und/oder Ende einer Zeichenkette.
VarSetCapacity Vergrößert die Aufnahmekapazität einer Variable oder gibt deren Speicher frei.

Mathematik

Funktion Beschreibung
Abs Gibt den absoluten Wert von Zahl zurück.
Ceil Gibt Zahl zurück, welche auf den nächsten Integer aufgerundet ist (ohne .00-Suffix).
Exp Gibt e zurück (ungefähr 2.71828182845905), potenziert mit N.
Floor Gibt Zahl zurück, welche auf den nächsten Integer abgerundet ist (ohne .00-Suffix).
Log Gibt den Logarithmus (Basis 10) von Zahl zurück.
Ln Ermittelt den Logarithmus (Basis e) von Zahl.
Mod Gibt den Rest zurück, wenn Dividend durch Divisor geteilt wird.
Round Gibt Zahl zurück, welche auf N Dezimalstellen gerundet ist.
Sqrt Gibt die Quadratwurzel von Zahl zurück.
Sin / Cos / Tan Gibt den trigonometrischen Sinus/Kosinus/Tangens von Zahl zurück.
ASin / ACos / ATan Gibt den Arkussinus/Arkuskosinus/Arkustangens als Bogenmaß zurück.

Sonstige Funktionen

Befehlsfunktionen von Polyethene: Bietet für jeden AutoHotkey-Befehl, der eine Ausgabevariable hat, eine aufrufbare Funktion. Diese Library kann per #Include in jedem Skript eingefügt werden.