Dieses Dokument enthält einige Themen, die manchmal wichtig sind, wenn externe Bibliotheken verwendet werden oder Meldungen an ein Steuerelement oder Fenster gesendet werden.
Hinweis: Dieser Abschnitt baut auf Themen auf, die in anderen Teilen der Dokumentation behandelt werden: Zeichenketten (Strings), Zeichenkettenkodierung.
Innerhalb einer Zeichenkette (Textwert) ist der numerische Zeichencode und die Größe (in Byte) jedes einzelnen Zeichens von der Kodierung der Zeichenkette abhängig. Solche Details sind in der Regel nur für Skripte interessant, die folgende Aktionen durchführen:
AutoHotkey v2 verwendet nativ Unicode (UTF-16), aber einige externe Bibliotheken oder Fenstermeldungen können ANSI-Zeichenketten erfordern.
ANSI: Jedes Zeichen ist ein Byte groß (8 Bits). Zeichencodes über 127 sind abhängig von den Spracheinstellungen Ihres Systems (oder von der Codepage, die bei der Kodierung des Textes gewählt wurde, z.B. beim Schreiben in eine Datei).
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-Codeeinheiten vertreten, ugs. "Ersatzzeichenpaar" (surrogate pair). Ebenso enthalten einige ANSI-Codepages (ugs. Doppelbyte-Zeichensätze) einige Doppelbyte-Zeichen. Aus praktischen Gründen werden diese jedoch fast immer als zwei einzelne Einheiten behandelt (der Einfachheit halber als "Zeichen" bezeichnet).
Achten Sie bei der Reservierung eines Pufferspeichers via Buffer darauf, dass Sie die korrekte Anzahl von Bytes für die jeweils benötigte Kodierung angeben. Zum Beispiel:
ansi_buf := Buffer(Kapazität_in_Zeichen) utf16_buf := Buffer(Kapazität_in_Zeichen * 2)
Wenn eine ANSI- oder UTF-8-Zeichenkette mit StrPut in den Pufferspeicher geschrieben wird, sollten Sie keinesfalls StrLen zur Bestimmung der Puffergröße verwenden, da die ANSI- oder UTF-8-Länge von der nativen Länge (UTF-16) abweichen kann. Verwenden Sie stattdessen StrPut, um die erforderliche Puffergröße zu berechnen. Zum Beispiel:
required_bytes := StrPut(source_string, "cp0") ansi_buf := Buffer(required_bytes) StrPut(source_string, ansi_buf)
Verwendet man den "Str"-Typ, handelt es sich um 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 | Kodierung | |
---|---|---|---|
WStr | 16-Bit | wchar_t*, WCHAR*, LPWSTR, LPCWSTR | UTF-16 |
AStr | 8-Bit | char*, CHAR*, LPSTR, LPCSTR | ANSI (die Standard-ANSI-Codepage des Systems) |
Str | -- | TCHAR*, LPTSTR, LPCTSTR | Äquivalent zu WStr in AutoHotkey v2. |
Wenn "Str" oder "WStr" für einen Parameter verwendet wird, wird die Adresse der Zeichenkette an die Funktion übergeben. Bei "AStr" wird eine temporäre ANSI-Kopie der Zeichenkette erstellt und die Adresse dieser Kopie übergeben. Generell sollte "AStr" nicht für einen Ausgabeparameter verwendet werden, da der Pufferspeicher gerade groß genug für die Eingabezeichenkette ist.
Hinweis: "AStr" und "WStr" können sowohl für die Parameter als auch für den Rückgabewert der Funktion verwendet werden.
Wenn ein Skript eine Funktion via DllCall aufruft, die eine Zeichenkette als Parameter akzeptiert, muss eine oder mehr der folgenden Vorgehensweisen verwendet werden:
DeleteFileA
und DeleteFileW
exportiert. Da DeleteFile
selbst nicht wirklich existiert, versucht DllCall automatisch DeleteFileW
:
DllCall("DeleteFile", "Ptr", StrPtr(DateiName)) DllCall("DeleteFile", "Str", DateiName)
In beiden Fällen wird die Adresse der originalen, unveränderten Zeichenkette an die Funktion übergeben.
In einigen Fällen kann dieser Ansatz nach hinten losgehen, da DllCall nur dann das Suffix W hinzufügt, wenn keine Funktion mit dem originalen Namen gefunden werden konnte. Zum Beispiel exportiert shell32.dll ExtractIconExW, ExtractIconExA und ExtractIconEx ohne Suffix, wobei die letzten beiden äquivalent sind. In diesem Fall bewirkt das Weglassen des Suffixes W, dass die ANSI-Version aufgerufen wird.
DllCall("DeleteFileA", "AStr", DateiName) DllCall("DeleteFileW", "WStr", DateiName)
Wenn NumPut oder NumGet mit Zeichenketten verwendet werden, muss der Offset und Typ für den angegebenen Zeichenkettentyp korrekt sein. Folgendes kann Ihnen dabei helfen:
; 8-bit/ANSI strings: size_of_char=1 type_of_char="UChar" ; 16-Bit/UTF-16 Zeichenketten: size_of_char=2 type_of_char="UShort" nth_char := NumGet(buffer_or_address, (n-1)*size_of_char, type_of_char) NumPut(type_of_char, nth_char, buffer_or_address, (n-1)*size_of_char)
Für das erste Zeichen sollte n den Wert 1 haben.
Pointer sind in 32-Bit-Builds 4 Bytes und in 64-Bit-Builds 8 Bytes groß. Skripte, die Strukturen oder DllCalls verwenden, sollten das berücksichtigen, um eine korrekte Ausführung auf beiden Plattformen zu gewährleisten. Bestimmte Bereiche, die auch betroffen sind:
Für Größen- und Offset-Berechnungen kann A_PtrSize verwendet werden. Für DllCall, NumPut und NumGet kann je nach Bedarf der Ptr-Typ verwendet werden.
Beachten Sie, dass der Offset eines Feldes ü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; */ pi := Buffer(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")