本書では、外部ライブラリとの連携や、コントロールやウィンドウへのメッセージ送信の際に重要となるトピックをいくつか紹介します。
注:このセクションは、ドキュメントの他の部分でカバーされているトピックを構築しています:文字列、文字列のエンコード。
文字列(テキスト値)の中で、各文字の数値文字コードとサイズ(バイト数)は、文字列のエンコーディングに依存します。これらの詳細は、通常、次のいずれかを実行するスクリプトで重要です:
AutoHotkey v2はネイティブでUnicode(UTF-16)を使用しますが、一部の外部ライブラリやウィンドウメッセージではANSI文字列を必要とする場合があります。
ANSI:1文字が1バイト(8ビット)です。127以上の文字コードは、お使いのシステムの言語設定(または、ファイルへの書き込みなど、テキストをエンコードする際に選択されたコードページ)に依存します。
Unicode:各文字は2バイト(16ビット)です。文字コードは、UTF-16形式で定義されたものです。
意味:技術的には、一部のUnicode文字は2つの16ビットコードユニットで表され、集合的に "サロゲートペア "として知られています。同様に、いくつかのANSIコードページ(一般にダブルバイト文字セットとして知られている)には、いくつかのダブルバイト文字が含まれています。しかし、実用上の理由から、これらはほとんどの場合、2つの個別のユニット(簡単のために「文字」と呼ばれる)として扱われます。
バッファを割り当てる際には、必要なエンコーディングに応じた正しいバイト数を計算するように注意してください。事例:
ansi_buf := Buffer(capacity_in_chars) utf16_buf := Buffer(capacity_in_chars * 2)
StrPutでANSIまたはUTF-8の文字列をバッファに書き込む場合、ANSIまたはUTF-8の長さがネイティブ(UTF-16)の長さと異なる場合があるので、バッファのサイズを決めるのにStrLenを使用しないでください。代わりに、StrPutを使用して必要なバッファサイズを計算します。事例:
required_bytes := StrPut(source_string, "cp0") ansi_buf := Buffer(required_bytes) StrPut(source_string, ansi_buf)
"Str"型が使用される場合、現在のビルドのネイティブフォーマットの文字列を意味します。関数によっては、特定の形式の文字列を要求したり、返したりすることがあるため、次のような文字列型を用意しています:
文字サイズ | C / Win32 Types | エンコード | |
---|---|---|---|
WStr | 16-bit | wchar_t*、WCHAR*、LPWSTR、LPCWSTR | UTF-16 |
AStr | 8-bit | char*、CHAR*、LPSTR、LPCSTR | ANSI(システムデフォルトのANSIコードページ) |
Str | -- | TCHAR*、LPTSTR、LPCTSTR | AutoHotkey v2 のWStrに相当します。 |
パラメータに "Str" または "WStr" を使用した場合、文字列のアドレスが関数に渡されます。"AStr"の場合、文字列の一時的なANSIコピーが作成され、そのアドレスが代わりに渡されます。バッファは入力文字列を保持するのに十分な大きさしかないため、原則として "AStr"を出力パラメータに使用するべきではありません。
注:"AStr"および "WStr"は、パラメータおよび関数の戻り値に対して同様に有効です。
一般に、スクリプトがDllCallを介して、文字列をパラメータとして受け付ける関数を呼び出す場合、以下のアプローチのうちの1つ以上を取る必要があります:
DeleteFileA
と DeleteFileW
としてkernel32.dllからエクスポートされます。DeleteFile
自体は実際には存在しないので、DllCallは自動的にDeleteFileW
を試行します:
DllCall("DeleteFile", "Ptr", StrPtr(filename)) DllCall("DeleteFile", "Str", filename)
どちらの場合も、修正されていない元の文字列のアドレスが関数に渡されます。
DllCallは、元の名前の関数が見つからなかった場合にのみ、Wサフィックスを追加するため、この方法が裏目に出る場合もあります。例えば、shell32.dllはExtractIconExW、ExtractIconExA、ExtractIconExをサフィックスなしでエクスポートし、最後の2つは同等です。その場合、Wサフィックスを省略すると、ANSIバージョンが呼び出されることになります。
DllCall("DeleteFileA", "AStr", filename) DllCall("DeleteFileW", "WStr", filename)
NumPutまたはNumGetが文字列と共に使用される場合、オフセットと型は与えられた文字列の型に対して正しくなければならない。以下は目安としてお使いください:
; 8-bit/ANSI strings: size_of_char=1 type_of_char="UChar" ; 16-bit/UTF-16 strings: 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)
最初の文字については、nは値1でなければならない。
ポインターは32ビットビルドでは4バイト、64ビットビルドでは8バイトです。構造体やDllCallを使用するスクリプトは、両方のプラットフォームで正しく実行するために、これを考慮する必要があります。影響を受ける具体的な地域は以下の通りです:
サイズとオフセットの計算には、A_PtrSizeを使用します。DllCall、NumPut、NumGetについては、適宜Ptr型を使用します。
フィールドのオフセットは、通常、そのフィールドに先行するすべてのフィールドの合計サイズであることを忘れないでください。また、ハンドル(HWNDやHBITMAPなどの型も含む)は基本的にポインタ型であることに注意してください。
/* 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", <omitted for brevity>, "Ptr", &pi, <omitted>) hProcess := NumGet(pi, 0) ; デフォルトは "Ptr"です。 hThread := NumGet(pi, A_PtrSize) ; dwProcessId := NumGet(pi, A_PtrSize*2, "UInt") dwProcessId := NumGet(pi, A_PtrSize*2 + 4, "UInt")