Obwohl viele Skripte, die noch auf AutoHotkey 1.0 basieren, nicht für AutoHotkey 1.1 geändert werden müssen, kann es passieren, dass einige Skripte fehlerhaft funktionieren werden, weil beide Versionen notwendige Unterschiede aufweisen. Die meisten Benutzer müssen sich keine Sorgen machen, da die schwerwiegenden Unterschiede nur erweiterte Funktionalitäten wie DllCall() betreffen.
AutoHotkey 1.1 kennt man auch unter den Namen "AutoHotkey_L". AutoHotkey 1.0 hat seit längerer Zeit die Bezeichnung "AutoHotkey Basic". Ältere Versionen von AutoHotkey_L haben noch eine Versionsnummer im Format 1.0.*, daher wird sich dieses Dokument stattdessen auf die Namen der beiden Entwicklungszweige von AutoHotkey beziehen, um Missverständnisse vorzubeugen.
Hinweis: Einige der häufigsten Probleme werden durch Änderungen verursacht, die erforderlich waren, um Unicode-Text zu unterstützen. Mit der ANSI-Version von AutoHotkey_L können solche Probleme umgangen werden.
Hohe Auswirkung:
Mittlere Auswirkung:
x & y::
bewirkt, dass sowohl x::
als auch x up::
ausgelöst werden, sobald x losgelassen wirdNiedrige Auswirkung:
Bestimmte Syntaxfehler, die bei AutoHotkey Basic toleriert wurden, sind bei AutoHotkey_L nicht mehr zugelassen. Viele dieser Fehler können einfach korrigiert werden, sobald sie entdeckt werden. In AutoHotkey_L werden die folgenden Fehler sofort nach dem Starten eines Skripts erkannt - solche Fehler müssen korrigiert werden, um das Skript überhaupt lauffähig zu machen:
MsgBox< foo
und If!foo
keine gültigen Angaben.Hotkey, IfIrgendetwas
, bei dem Irgendetwas ungültig ist, wird nicht toleriert.Einige Syntaxfehler werden erkannt, während das Skript läuft. Das Skript wird eine Fehlermeldung anzeigen, bevor es den aktuellen Thread verlässt:
Andere Syntaxfehler wiederum werden überhaupt nicht erkannt, was bei AutoHotkey_L zu Problemen führen kann:
(
ist selektiver, so dass ungültige Ausdrücke wie 12(34)
nicht mehr funktionieren werden.FileRead wandelt den Zeichensatz des Textes in bestimmten Fällen um, dadurch kann es passieren, dass dieser Befehl beschädigte Binärdaten zurückgibt. Um das zu umgehen, können Sie die *c
-Option hinzufügen oder stattdessen FileOpen() verwenden.
Die Zeichen [
, ]
und ?
sind für die Verwendung in Ausdrücken reserviert und daher nicht länger in Variablennamen gültig. Folglich benötigt ?
(das in ternären Operationen benutzt wird) nicht länger ein Leerzeichen auf jeder Seite. Siehe auch Objektsyntax.
Fehler werden automatisch oder überhaupt nicht erkannt, je nachdem, welche Bedingungen zutreffen:
Array%n%
, wo n eins der oben genannten Zeichen enthält), wird eine Fehlermeldung beim Auswerten der Doppeldereferenzierung angezeigt, während das Skript läuft.DPI-Skalierung ist für Skript-GUIs standardmäßig aktiviert, um sicherzustellen, dass sie auf Basis der DPI-Einstellungen des Systems skaliert werden. Wenn sie aktiviert ist und wenn die DPI-Einstellung des Systems ungleich 96 (100 %) ist, sind Positionen und Größen, die von Gui-Befehlen akzeptiert oder zurückgegeben werden, nicht mit anderen Befehlen kompatibel. Mit Gui -DPIScale
kann die DPI-Skalierung deaktiviert werden.
In den Unicode-Versionen von AutoHotkey_L wurden einige Unterbefehle von Transform geändert oder entfernt:
Sobald man AutoHotkey_L ohne Angabe eines Skripts startet, wird standardmäßig eine AHK-Datei statt einer INI-Datei geladen. Der Name dieser Datei beruht auf dem Dateinamen der aktuell ausführbaren Datei. Weitere Informationen finden Sie unter Befehlszeilenparameter an ein Skript übergeben.
Wenn man ein großgeschriebenes H benutzt, werden die hexadezimale Zeichen A-F auch in Großbuchstaben sein. AutoHotkey Basic verwendet hingegen immer Kleinbuchstaben. Siehe SetFormat.
Die folgenden Befehle setzen nun A_LastError, um das Debuggen zu unterstützen: FileAppend, FileRead, FileReadLine, FileDelete, FileCopy, FileMove, FileGetAttrib/Time/Size/Version, FileSetAttrib/Time, FileCreateDir, RegRead, RegWrite, RegDelete. Sobald man einen dieser Befehle benutzt, wird der vorherige Wert von A_LastError überschrieben.
Die intelligente Kommahandhabung des MsgBox-Befehls wurde geändert, um ihn flexibler und konsistenter mit anderen Befehlen zu machen. In den meisten Fällen wird sich der MsgBox-Befehl wie vorgesehen verhalten. In einigen seltenen Fällen kann es vorkommen, dass Skripte, die noch auf das alte fehlerbehaftete Verhalten angewiesen sind, sich anders als sonst verhalten werden. Zum Beispiel:
; Dies wird nun getrennt als Ausdruck (Optionen) gefolgt von Text (Titel) interpretiert, ; anstatt als einzelner Ausdruck (Text) mit mehreren Teilausdrücken: MsgBox % x, y ; Mit runden Klammern kann die alte Interpretation erzwungen werden: MsgBox % (x, y) ; Dies wird nun ein leeres Dialogfenster anzeigen, anstatt den Text "0, Titel": MsgBox 0, Titel ; Diese verhalten sich in AutoHotkey_L und AutoHotkey Basic wie erwartet: MsgBox 0, Titel, % "" ; Zeigt ein leeres Dialogfenster an MsgBox 0`, Titel ; Zeigt den Text "0, Titel" an ; Dies wird nun ein leeres Dialogfenster anzeigen, anstatt den Text ", Titel": MsgBox,, Titel
Sobald man die +Owner-Option auf eine GUI anwendet, wird außerdem der WS_CHILD-Style entfernt und der WS_POPUP-Style gesetzt. Diese Änderung kann bewirken, dass Skripte, die mit +Owner
das übergeordnete Fenster einer GUI nach Festlegen der Styles setzen, nicht mehr ordnungsgemäß funktionieren werden.
SoundSet, SoundGet, SoundSetWaveVolume und SoundGetWaveVolume werden in Windows Vista oder höher besser unterstützt. Folgende Änderungen treten dabei in Kraft:
In [v1.1.14+] hat das Tilde-Präfix Einfluss darauf, wie eine Taste funktioniert, wenn sie als Modifikatortaste in einer benutzerdefinierten Tastenkombination verwendet wird.
Wenn ein KeyDown- und KeyUp-Hotkey für eine benutzerdefinierte Modifikatortaste definiert wurde, werden beide beim Loslassen der Taste ausgelöst (sofern das Tilde-Präfix nicht vorhanden ist). Zum Beispiel würde x & y::
bewirken, dass x::
und x up::
erst ausgelöst werden, wenn x losgelassen wird. Vorher wurde x::
dabei nie ausgelöst.
If Var is Typ ignoriert die Sprach- und Regionseinstellungen des Systems, es sei denn, StringCaseSense Locale wurde verwendet.
GroupActivate setzt ErrorLevel auf 1, wenn kein einziges Fenster aktiviert werden konnte, ansonsten auf 0. Zuvor blieb ErrorLevel unverändert.
Der Label-Parameter von GroupAdd gilt für die gesamte Fenstergruppe und nicht für eine bestimmte Fensterspezifikation innerhalb der Gruppe. Eine Diskussion zu dieser Änderung kann im Forum gefunden werden. Allerdings ist dieser Parameter nicht empfohlen; überprüfen Sie stattdessen ErrorLevel, nachdem Sie GroupActivate aufgerufen haben.
AutoHotkey_L enthält Verbesserungen bezüglich der Verfahrensweise, wie Run und RunWait ihren Ziel-Parameter interpretieren. Diese Verbesserungen bieten neue Möglichkeiten, die zuvor nicht möglich waren, aber können bereits existierende Skripte beeinträchtigen, die auf Basis von AutoHotkey Basic erstellt wurden. Das neue Verhalten äußert sich wie folgt:
Loop Read und FileReadLine interpretieren das Zeichen Strg+Z (0x1A) nicht länger als Dateiendemarke (end-of-file marker). Jedes Strg+Z-Zeichen wird so wie es ist geladen, selbst wenn es ganz am Ende einer Datei vorkommt. FileRead ignoriert bereits dieses Zeichen und ist daher von diesem Problem nicht betroffen.
Setzt man den Kompatibilitätsmodus auf Windows 95, NT4 oder 98/ME im Eigenschaftsfenster der EXE-Datei, mit der das Skript ausgeführt werden soll, kann es passieren, dass sich das Skript falsch verhalten wird. Das liegt daran, dass der Kompatibilitätsmodus eine bestimmte Windows-Version an das Programm senden würde, die in AutoHotkey_L nicht mehr unterstützt wird. Setzt man den Kompatibilitätsmodus auf Windows 95 oder 98/ME, würde MsgBox %A_OSVersion%
die Version WIN_NT4
melden.
A_IsCompiled wird als leere Zeichenkette definiert, wenn das Skript noch nicht kompiliert wurde. Vorher blieb es undefiniert, wodurch Zuweisungen wie A_IsCompiled := 1
möglich waren, sofern das Skript noch nicht kompiliert wurde. Jedenfalls wird sie nun als schreibgeschützte interne Variable behandelt.
Escapezeichenversehene Leerraumzeichen wie `t
und `
werden nicht länger am Anfang oder am Ende eines Arguments verworfen. Zum Beispiel ist StringReplace s, s, `t
nun eine gültige Anweisung, die alle Tabulatorzeichen in s entfernt.
Hinweis: Dieser Abschnitt baut auf Themen auf, die in anderen Teilen der Dokumentation behandelt werden: Zeichenketten (Strings), Zeichenkettencodierung.
Innerhalb einer Zeichenkette (Textwert) ist der numerische Zeichencode und die Größe (in Byte) jedes einzelnen Zeichens von der nativen Codierung des Skripts und von der AutoHotkey-EXE-Datei abhängig; also Unicode oder ANSI. Solche Details sind in der Regel nur für Skripte interessant, die folgende Aktionen durchführen:
Skripte, die nur für ein bestimmtes Format gedacht waren, werden oft auf Probleme stoßen, wenn sie mit der falschen AutoHotkey-Version laufen. Zum Beispiel werden einige Skripte, die noch auf AutoHotkey Basic basieren, korrekt mit der ANSI-Version von AutoHotkey_L funktionieren, aber nicht mit der Unicode-Version. Mit dem folgenden Skript kann man herausfinden, welche Version aktuell verwendet wird:
MsgBox % A_IsUnicode ? "Unicode" : "ANSI"
ANSI: Jedes Zeichen ist ein Byte groß (8 Bits). Zeichencodes über 127 sind von den Spracheinstellungen Ihres Systems abhängig.
Unicode: Jedes Zeichen ist zwei Bytes groß (16 Bits). Zeichencodes sind durch das UTF-16-Format definiert.
Semantischer Hinweis: Technisch gesehen sind einige Unicode-Zeichen durch zwei 16-Bit-Code-Einheiten vertreten, auch allgemein bekannt als "Ersatzzeichenpaar" (surrogate pair). Ebenso enthalten einige ANSI-Zeichensätze (allgemein bekannt als Doppel-Byte-Zeichensätze) einige Doppel-Byte-Zeichen. Allerdings werden solche aus praktischen Gründen fast immer als zwei einzelne Einheiten (bzw. Zeichen) behandelt.
VarSetCapacity bestimmt die Kapazität einer Variable in Bytes. Um die Kapazität einer Variable in Bezug auf die Zeichenanzahl zu setzen, muss die Größe eines Zeichens berücksichtigt werden. Zum Beispiel:
VarSetCapacity(ansi_var, capacity_in_chars) VarSetCapacity(unicode_var, capacity_in_chars * 2) VarSetCapacity(native_var, capacity_in_chars * (A_IsUnicode ? 2 : 1)) VarSetCapacity(native_var, t_size(capacity_in_chars)) ; siehe unten
Es gibt zwei Anwendungsmöglichkeiten für VarSetCapacity:
VarSetCapacity(var, 1000)
1000 Bytes ermöglichen; in den Unicode-Versionen von AutoHotkey_L wären das nur 500 Zeichen. Das könnte Einfluss auf die Leistung haben, aber das Skript selbst sollte weiterhin normal funktionieren.Der "Str"-Typ, falls vorhanden, kennzeichnet eine Zeichenkette im nativen Format des aktuellen Builds. Da einige Funktionen möglicherweise Zeichenketten in einem bestimmten Format benötigen oder zurückgeben müssen, stehen folgende Zeichenkettentypen zur Verfügung:
Zeichengröße | C / Win32-Typen | Codierung | |
---|---|---|---|
WStr | 16-Bit | wchar_t*, WCHAR*, LPWSTR, LPCWSTR | UTF-16 |
AStr | 8-Bit | char*, CHAR*, LPSTR, LPCSTR | ANSI (der Standard-ANSI-Zeichensatz des Systems) |
Str | -- | TCHAR*, LPTSTR, LPCTSTR | Entspricht WStr in Unicode-Builds und AStr in ANSI-Builds. |
Verwendet man "Str" oder das Gegenstück des aktuellen Builds als Parameter, wird die Adresse der Zeichenkette oder Variable an die Funktion übergeben. Ansonsten wird eine temporäre Kopie der Zeichenkette im gewünschten Format erstellt und diese stattdessen übergeben. In der Regel sollten "AStr" und "WStr" nicht verwendet werden, wenn die Funktion einen Wert in diesen Parameter schreibt.
Hinweis: "AStr" und "WStr" sind sowohl bei Parametern als auch beim Rückgabewert einer Funktion gültig.
Wenn ein Skript eine Funktion via DllCall() aufruft, die eine Zeichenkette als Parameter akzeptiert, muss eine der folgenden Methoden durchgeführt werden:
DllCall("DeleteFile", "Ptr", &DateiName) DllCall("DeleteFile", "Str", DateiName)
In diesem Beispiel wird &DateiName
die Adresse der Zeichenkette exakt in dieser Form übergeben, so dass die Funktion eine Zeichenkette im gleichen Format wie der "Str"-Typ erwarten muss. Beachten Sie, dass in AutoHotkey Basic "UInt" statt "Ptr" verwendet werden muss, aber es kann sein, dass der resultierende Code nicht 64-Bit-kompatibel ist.
Hinweis: Wenn die Funktion mit exakt diesem Namen nicht auffindbar ist, fügt AutoHotkey_L das Suffix "A" oder "W" an, egal welche DLL-Datei angegeben ist. AutoHotkey Basic hingegen wird das Suffix "A" nur bei Funktionen anfügen, die in User32.dll, Kernel32.dll, ComCtl32.dll oder Gdi32.dll vorkommen.
DllCall("DeleteFileA", "AStr", DateiName) DllCall("DeleteFileW", "WStr", DateiName)
Wenn man NumPut() oder NumGet() bei Zeichenketten anwendet, muss der korrekte Offset und Typ für den angegebenen Zeichenkettentyp angegeben werden. Das folgende Beispiel könnte Ihnen dabei helfen:
; 8-Bit/ANSI Zeichenketten: size_of_char=1 type_of_char="Char" ; 16-Bit/UTF-16 Zeichenketten: size_of_char=2 type_of_char="UShort" nth_char := NumGet(var, (n-1)*size_of_char, type_of_char) NumPut(nth_char, var, (n-1)*size_of_char, type_of_char)
Wenn var
eine Zeichenkette im nativen Format enthält, können die passenden Werte auf Basis von A_IsUnicode
bestimmt werden:
nth_char := NumGet(var, t_size(n-1), t_char()) NumPut(nth_char, var, t_size(n-1), t_char()) ; Definieren Sie Funktionen für Komfort und Übersichtlichkeit: t_char() { return A_IsUnicode ? "UShort" : "Char" } t_size(char_count=1) { return A_IsUnicode ? char_count*2 : char_count }
Pointer sind in 32-Bit-Builds (einschließlich AutoHotkey Basic) 4 Bytes groß und in 64-Bit-Builds 8 Bytes. Skripte, die Strukturen oder DllCalls verwenden, sollten dies berücksichtigen, um eine korrekte Ausführung auf beiden Plattformen zu gewährleisten. Bestimmte Bereiche, die auch betroffen sind:
Mit A_PtrSize kann man Größe und Offset berechnen. Je nachdem wo es angebracht ist, kann man den Ptr-Typ bei DllCall(), NumPut() und NumGet() verwenden.
Beachten Sie, dass der Offset eines Felds üblicherweise die Gesamtgröße aller vorherigen Felder ist. Beachten Sie auch, dass Handles (einschließlich Typen wie HWND und HBITMAP) prinzipiell Pointer-Typen sind.
/* typedef struct _PROCESS_INFORMATION { HANDLE hProcess; // Ptr HANDLE hThread; DWORD dwProcessId; // UInt (4 Bytes) DWORD dwThreadId; } PROCESS_INFORMATION, *LPPROCESS_INFORMATION; */ VarSetCapacity(pi, A_PtrSize*2 + 8) ; Ptr + Ptr + UInt + UInt DllCall("CreateProcess", <gekürzt>, "Ptr", &pi, <gekürzt>) hProcess := NumGet(pi, 0) ; Standardmäßig "Ptr". hThread := NumGet(pi, A_PtrSize) ; dwProcessId := NumGet(pi, A_PtrSize*2, "UInt") dwProcessId := NumGet(pi, A_PtrSize*2 + 4, "UInt")