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 (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; 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 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, definiert man 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 performanter 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. Optionale Parameter haben rechts daneben ein Gleichheitszeichen (oder seit v1.1.09 :=) und einen Standardwert. Die folgende Funktion hat einen Z-Parameter, der als optional gekennzeichnet ist:

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

Ab v1.1.09 kann sowohl = als auch := zum Definieren eines optionalen Parameters verwendet werden. Es ist ratsam, Letzteres zu verwenden, um konsistent mit Ausdruckszuweisungen und kompatibel mit zukünftigen AutoHotkey-Versionen zu sein.

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

Es ist nicht möglich, optionale Parameter in der Mitte der Parameterliste zu platzieren. Alle Parameter auf der rechten Seite des ersten optionalen Parameters müssen in diesem Fall auch optional 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.

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

In v1.0.46.13+ können ByRef-Parameter auch optional sein; zum Beispiel: Funk(ByRef p1 = ""). Jedes Mal, 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.

Der Standardwert eines Parameters kann Folgendes sein: True, False, ein direkt geschriebener Integer, eine direkt geschriebene Gleitkommazahl oder eine direkt geschriebene Zeichenkette wie "fox" oder "" (Zeichenketten unterstützen vor v1.0.46.13 nur "").

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:

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

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.

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

Siehe unten, wie das Standardverhalten überschrieben werden kann.

Globale Variablen

Um innerhalb einer Funktion auf eine vorhandene globale Variable zu verweisen (oder eine neue zu erstellen), deklariert man die Variable als globale Variable, 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 eine lokale Variable deklariert sein. 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 - 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. 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:

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; um also zu erkennen, ob statische Variablen zum ersten Mal verwendet wurden, musste man überprüfen, ob sie leer waren. In v1.0.46+ kann eine statische Variable mit etwas anderes als "" initialisiert werden, indem man mithilfe von := oder = einen der folgenden Wertetypen zuweist: True, False, ein direkt geschriebener Integer, eine direkt geschriebene Gleitkommazahl oder eine direkt geschriebene 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.

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

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

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

In v1.0.46+ kann eine lokale oder globale Variable auf derselben Zeile sowohl deklariert als auch initialisiert werden, indem man mithilfe von := oder = einen Ausdruck zuweist (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 die Ablaufsteuerung 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. Das heißt, dass eine Deklaration innerhalb eines IF- oder ELSE-Blocks auf alle Zeilen zwischen der Deklaration und der geschweiften Endklammer der Funktion eine Auswirkung hat. 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 global-behandelnder 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).

Innerhalb einer Funktion wird jeder dynamische Variablenverweis wie Array%i% in eine lokale Variable aufgelöst. Wenn eine lokale Variable mit diesem Namen nicht existiert, wird eine globale Variable verwendet, sofern sie vorhanden ist. 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 global-behandelnder Modus nicht aktiv ist. Eine Funktion kann ein globales Array demzufolge nur erstellen (z. B. via Array%i% := A_Index), wenn der global-behandelnder Modus aktiv ist.

Häufiger Anlass zu Verwirrung: Jeder nicht-dynamische Verweis auf eine 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 global-behandelnder Modus nicht aktiv ist), auch dann, wenn Array und Array0 als global deklariert sind.

Dynamisches Aufrufen einer Funktion

In v1.0.47.06+ kann eine Funktion (auch eine interne Funktion) 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.

In v1.1.07.00+ kann Var in %Var%() einen Funktionsnamen oder ein Funktionsobjekt enthalten. Wenn die Funktion nicht existiert, wird stattdessen die __Call-Meta-Funktion des Standard-Base-Objekts 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.

Logische Kurzschlussauswertung

AND, OR und der ternäre Operator innerhalb eines Ausdrucks reduzieren die Auswertung auf ein Minimum, 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 abläuft:

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

Wenn die FarbName-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 FarbName z. B. im folgenden Ausdruck leer ist, wird nur der am weitesten links befindliche Vergleich durchgeführt, weil die linke Seite dann ausreichen würde, um das Endergebnis zweifelsfrei 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 umfangreiche (zeitaufwendige) Funktionen in der Regel auf der rechten Seite von AND oder OR aufgerufen werden, um die Performance 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).

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

Verwenden von Subroutinen innerhalb einer Funktion

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 Beenden des aktuellen Threads verwendet, erhält ihr Aufrufer überhaupt keinen Rückgabewert. Das Var in Var := Addieren(2, 3) bliebe beispielsweise unverändert, wenn Add() 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, verwendet man ein leeres Anführungszeichen-Paar. Zum Beispiel: FindeFarbe(FarbName, "").

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 global-behandelnder Modus wirksam ist).

ListVars kann, wenn es in einer Funktion verwendet wird, die Namen und Inhalte von lokalen Variablen anzeigen. Dies kann dazu beitragen, ein Skript zu debuggen.

Stil- und Namenskonventionen

Komplexe Funktionen sind besser lesbar und verwaltbar, wenn ihre speziellen Variablen mit einem eindeutigen Präfix benannt werden. Die Parameter einer Funktion können beispielsweise mit einem führenden "p" oder "p_" benannt werden, damit sie 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. Eine oder mehrere Funktionsdefinitionen im obersten Bereich eines Skripts haben 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 Library - benötigt AHK_L 42+.
%A_MyDocuments%\AutoHotkey\Lib\  ; Benutzer-Library.
Pfad-zur-gerade-laufenden-AutoHotkey.exe\Lib\  ; Standard-Library.

Wenn ein Skript beispielsweise die nicht-existierende Funktion MeineFunktion() aufruft, durchsucht das Programm die Benutzerbibliothek nach einer Datei namens "MeineFunktion.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_MeineFunktion), 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_MeineFunktion 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 von der Performance her genauso gut 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 mehr Details zu einer bestimmten internen Funktion zu erhalten, klickt man einfach auf einen der unteren 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 die angegebene Taste unten ist, und False (0), wenn sie oben ist.
InStr Sucht von links nach rechts das erste Vorkommen einer Zeichenkette.
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 der Zeichen, die in einer Zeichenkette enthalten sind.
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 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 Ermöglicht eine objektorientierte Dateibearbeitung.
Format Formatiert eine variable Anzahl von Eingabewerten, basierend auf eine Formatzeichenkette.
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 die angegebene Variable für einen bestimmten ByRef-Parameter bereitgestellt 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 Meldung/ein Ereignis.
Ord Gibt den Ordinalwert (numerischen Zeichencode) des ersten Zeichens in der angegebenen Zeichenkette zurück.
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 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 Gibt den Logarithmus (Basis e) von Zahl zurück.
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 Bibliothek kann via #Include in einem beliebigen Skript eingebunden werden.