Windows標準のAPI関数など、DLL内部の関数を呼び出します。
Result := DllCall("DllFile\Function" , Type1, Arg1, Type2, Arg2, "Cdecl ReturnType")
DLLまたはEXEのファイル名の後にバックスラッシュを付け、関数名を指定します。事例:"MyDLL\MyFunction"(ファイル拡張子".dll "は省略時のデフォルトです)。絶対パスが指定されない場合、DllFileはシステムのPATHまたはA_WorkingDirにあるとみなされます。なお、DllCallはバックスラッシュを含むパスを想定しています(\)。フォワードスラッシュ(/)はサポートされていません。
User32.dll、Kernel32.dll、ComCtl32.dll、Gdi32.dllに存在する関数を呼び出す場合、DllFileを省略することができます。例えば、"User32\IsWindowVisible"は"IsWindowVisible"と同じ結果を得ることができる。
指定された名前の関数が見つからない場合は、自動的に "W"(ユニコード)の接尾辞が付加されます。例えば、"MessageBox"は"MessageBoxW"と同じです。
DLLを繰り返し呼び出す場合、あらかじめロードしておくことでパフォーマンスを飛躍的に向上させることができます。
このパラメータは、呼び出す関数のアドレスとして解釈される整数値のみからなることもあります。このようなアドレスのソースには、COMと CallbackCreateがあります。
このパラメータがオブジェクトである場合、オブジェクトのPtrプロパティの値が使用されます。そのようなプロパティが存在しない場合、PropertyErrorが投げられる。
型:文字列
これらのペアはそれぞれ、関数に渡される1つのパラメータを表しています。組数は無制限です。タイプについては、以下のタイプ表をご覧ください。Argの場合、関数に渡す値を指定します。
型:文字列
ほとんどの関数は「C」呼び出し規約ではなく、標準呼び出し規約を使用しているため、Cdeclという言葉は通常省略されます(wsprintfのように様々な数の引数を受け付ける関数は例外です)。なお、オブジェクト指向のC++関数の多くはthiscallの規約を使用していますが、これはサポートされていません。
存在する場合、Cdeclという単語は、(もしあれば)戻り値の型の前に記載されるべきです。単語と単語の間は、スペースまたはタブで区切る。事例:"Cdecl Str"。
64ビットコードには個別の "C" 呼び出し規約が存在しないため、Cdeclを指定することができますが、AutoHotkeyの64ビットビルドには何の効果もありません。
ReturnType:関数が32ビット符号付き整数(Int)、BOOL、または何も返さない場合は、ReturnTypeを省略することができる。それ以外の場合は、以下の型式表からいずれかの引数型を指定します。接尾辞のアスタリスクにも対応しています。
DllCallは、Functionが返す実際の値を返します。Functionが値を返さない型の場合、結果は指定された戻り値の型(デフォルトでは整数)の未定義値です。
| 型 | 説明 |
|---|---|
| Str |
関数がパラメータの入力値よりも長い文字列を保存するように設計されている場合(またはパラメータが出力のみの場合)、推奨される方法は、wsprintfの例のように、Bufferを作成し、Ptr型を使ってそれを渡し、関数が戻った後にStrGetを使って文字列を取得する方法です。 そうでない場合は、関数を呼び出す前に、変数が十分な大きさであることを確認します。ここで、123はMyVarが保持しなければならない16ビット単位(緩やかに文字と呼ばれる)の数である、 Str引数は、数値( めったに使われないStr*arg型は、文字列のアドレスを含む一時変数のアドレスを渡します。関数が一時変数に新しいアドレスを書き込むと、VarRefが渡された場合、新しい文字列はスクリプトの変数にコピーされます。これは、"TCHAR **"や "LPTSTR *"のようなものを期待する関数で使用することができます。しかし、関数がメモリを確保し、呼び出し側がそれを解放することを期待する場合(CoTaskMemFreeを呼び出すなど)、代わりに |
| WStr | AutoHotkeyはUTF-16をネイティブで使用するため、WStr(ワイド文字列)はStrと同等です。 |
| AStr |
AStr を指定すると、入力値が自動的に ANSI に変換されます。この変換に使用される一時メモリは、変換された入力文字列分の大きさしかないため、関数によって書き込まれた値は破棄されます。出力パラメータとしてANSI文字列を受け取るには、次の例に従います: buf := Buffer(length) ; 一時的なバッファを確保します。
DllCall("Function", "ptr", buf) ; バッファを関数に渡す。
str := StrGet(buf, "cp0") ; バッファからANSI文字列を取得します。
まれに使われるAStr*arg型もサポートされており、新しい文字列がANSIからネイティブフォーマットであるUTF-16に変換される以外はStr*型と同様の動作をします。 同等のWin32型などについては、「バイナリ互換性」を参照してください。 |
| Int64 | 64ビット整数で、範囲は-9223372036854775808(-0x800000000000)~9223372036854775807(0x7FFFFFFFFFFFF)です。 |
| Int | 32ビット整数(最も一般的な整数型)で、その範囲は-2147483648(-0x80000000)~2147483647(0x7FFFFFFFF)です。Intは "Long "と呼ばれることもあります。 また、関数が期待するBOOL引数(BOOL値は1か0のどちらかでなければならない)には、Intを使用しなければならない。 また、符号なしInt(UInt)はDWORDなど、かなり頻繁に使用されます。 |
| Short | 16ビットの整数で、範囲は-32768(-0x8000)~32767(0x7FFF)です。符号なしショート(UShort)は、WORDを期待する関数で使用することができます。 |
| Char | 8ビットの整数で、範囲は-128(-0x80)~127(0x7F)です。符号なし文字(UChar)は、BYTEを期待する関数で使用することができます。 |
| Float | 32ビット浮動小数点数で、6桁の精度を持つ。 |
| Double | 64ビットの浮動小数点数で、15桁の精度を持つ。 |
| Ptr | ポインタサイズの整数で、スクリプトを実行するexeが32ビットか64ビットかに応じて、IntまたはInt64に相当します。Ptrは、配列や構造体へのポインタ(RECT*やLPPOINTなど)や、ほとんどすべてのハンドル(HWND、HBRUSH、HBITMAPなど)に使用する必要があります。パラメータがLPDWORDやint*のような単一の数値へのポインタの場合、一般に "Ptr"の代わりに*またはP接尾辞を使用する必要があります。 Ptrパラメータにオブジェクトが渡された場合、そのオブジェクトの Ptr*パラメータにオブジェクトが渡された場合、呼び出し前にオブジェクトの Ptrは接尾辞に*やPを付けて使うこともできます。LPVOID*などを使ってポインタを出力する関数と一緒に使う必要があります。 UPtrも有効ですが、AutoHotkeyは符号なし64ビット整数をサポートしていないため、32ビットビルドでは符号なしのみです。 注意:NULLハンドルまたはポインタを渡す場合は、整数0を渡します。 |
| *またはP (接尾) |
上記の型のいずれかにアスタリスク(オプションでその前にスペース)を付けると、値そのものではなく、引数のアドレスが渡されます(呼び出された関数は、それを受け入れるように設計されていなければなりません)。このような引数の値は関数によって変更される可能性があるため、引数としてVarRefを渡すと、関数が戻った後にその変数の内容が更新されます。例えば、次の呼び出しでは、MyVarの内容をアドレスでMyFunctionに渡しますが、MyFunctionによる変更を反映してMyVarも更新されます: 一般に、関数が "LP "で始まる引数型や戻り値を持つ場合、アスタリスクが使用されます。最も一般的な例はLPDWORDで、これはDWORDへのポインタです。DWORDは符号なし32ビット整数なので、LPDWORDを表すには "UInt*"または "UIntP "を使用します。LPTSTRのような文字列型、LPRECTのような構造体へのポインタ、配列にはアスタリスクを使うべきではありません。これらには、文字列、アドレス、Bufferのどれを渡すかによって、"Str"または"Ptr"を使うべきです。 注意:"Char*"は"Str"と同じではありません。"Char*"は8ビット数値のアドレスを渡すのに対し、"Str"は一連の文字のアドレスを渡しますが、これはAutoHotkeyのバージョンによって16ビット(ユニコード)または8ビット("AStr"の場合)であることがあります。同様に、"UInt*"は32ビット数値のアドレスを渡すので、関数が値の配列や32ビットより大きな構造体を期待する場合は使用しないでください。 AutoHotkeyの変数には固定型がないため、関数に渡されるアドレスは、呼び出し元の変数ではなく、一時メモリを指しています。 |
| U(接頭) | 上記の整数型の前にUを付けると、符号なし整数(UInt64、UInt、UShort、UChar)として解釈されます。厳密には、valueで渡される引数がunsignedかsignedかは関係ないので、戻り値やアスタリスク変数にのみ必要です(Int64を除く)。 符号なし引数に負の整数を指定した場合、整数は符号なし領域へ回り込みます。例えば、-1をUIntとして送信した場合、0xFFFFFFFとなります。 関数で生成される符号なし64ビット整数はサポートされていません。したがって、0x800000000000以上の数値を扱う場合は、U接頭辞を省略し、関数から受け取った負の値を大きな整数として解釈してください。例えば、Int64として-1を返す関数は、UInt64を返すように設計されている場合、実際には0xFFFFFFFFFFFFを返すことになります。 |
| HRESULT |
32ビット整数です。これは一般にCOM関数で使用され、接頭辞や接尾辞のない戻り値型としてのみ有効です。エラー値(FAILED マクロで定義される)は決して返されず、代わりにOSErrorが投げられる。したがって、戻り値は0~2147483647の範囲の成功コードとなります。 HRESULTは、ComCallのデフォルトの戻り値タイプです。 |
DllCallは、以下のいずれかの条件下でErrorを投げる:
Exception.Extraには、16進数のエラーコードが含まれます。Exception.Extraは例外コードを含む。例えば、0xC0000005は "アクセス違反"を意味します。このような場合、スレッドは(tryが使用されていない場合)中止されますが、アスタリスク変数はまだ更新されます。致命的な例外の例としては、NULL(0)のような無効なポインタを再参照することが挙げられます。Cdecl関数は、次の段落で説明するようなエラーを発生させることはないので、引数が少なすぎる場合に例外を発生させることがあります。Exception.Extraには、引数リストが不正確であったバイト数が格納されます。正の値の場合、引数が多すぎる(または引数が大きすぎる)か、CDeclが必要な呼び出しです。負の値であれば、渡された引数が少なすぎる。このような状況は、機能の確実な動作のために修正する必要があります。このエラーの存在は、例外が発生したことを示す場合もあります。なお、x64の呼び出し規約により、64ビットビルドではこのエラーは発生しない。内蔵の例外処理にもかかわらず、DllCallでスクリプトをクラッシュさせることは可能です。これは、関数が直接例外を発生させないが、不正なポインタや終端していない文字列など、不適切なものを生成する場合に起こる可能性がある。これは、スクリプトが不正なポインタや容量不足の"str"のような不適切な値を渡した場合、関数の責任ではないかもしれません。また、関数が返す普通の整数をアスタリスク変数や strと主張するなど、不適切な引数型や戻り値を指定した場合にも、スクリプトがクラッシュすることがあります。
組込変数A_LastErrorには、オペレーティングシステムのGetLastError()関数の結果が格納されます。
DLLを繰り返し呼び出す場合、明示的にロードすることでパフォーマンスを飛躍的に向上させることができます(User32などの標準的なDLLは常に常駐しているため必要ありません)。この方法によって、DllCallが内部でLoadLibraryとFreeLibraryを毎回呼び出す必要を回避することができます。事例:
hModule := DllCall("LoadLibrary", "Str", "MyFunctions.dll", "Ptr") ; ループ内でDllCallしてライブラリを読み込む必要を回避。
Loop Files, "C:\My Documents\*.*", "R"
result := DllCall("MyFunctions\BackupFile", "Str", A_LoopFilePath)
DllCall("FreeLibrary", "Ptr", hModule) ; メモリ節約のため、使用後はDLLをアンロードすることがあります。
; 関数のアドレスをあらかじめ調べておくことで、さらに高速なパフォーマンスを実現することができます。事例:
; 次の例では、DLLがまだロードされていない場合、GetModuleHandleの代わりにLoadLibraryを使用してください。
MulDivProc := DllCall("GetProcAddress", "Ptr", DllCall("GetModuleHandle", "Str", "kernel32", "Ptr"), "AStr", "MulDiv", "Ptr")
Loop 500
DllCall(MulDivProc, "Int", 3, "Int", 4, "Int", 3)
DllCallの第1パラメータが"MulDiv"などのリテラル文字列で、その関数を含むDLLがスクリプトの開始前に通常ロードされているか、#DllLoadで正常にロードされていれば、文字列は自動的に関数アドレスに解決されます。このビルトイン最適化は、上に示した例よりも効果的です。
最後に、文字列の長さを変えない関数に文字列変数を渡す場合、変数を"str"としてではなく、アドレスで渡す(例:StrPtr(MyVar))ことでパフォーマンスが向上します(特に文字列が非常に長い場合)。次の例は、文字列を大文字に変換するものです:DllCall("CharUpper", "Ptr", StrPtr(MyVar), "Ptr")。
構造体とは、メモリ上に隣接して格納されたメンバー(フィールド)の集合体です。ほとんどのメンバーが整数になる傾向があります。
構造体(またはメモリブロック配列)のアドレスを受け取る関数は、何らかの方法でメモリを確保し、そのメモリアドレスを関数に渡すことで呼び出すことができます。この目的には、Bufferオブジェクトが推奨されます。一般的には以下の手順で行われます:
1)MyStruct := Buffer(123, 0)を呼び出して、構造体のデータを保持するバッファを確保します。123を構造体のサイズと同じ大きさ以上の数値(バイト数)に置き換えてください。最後のパラメータにゼロを指定することはオプションです。これは、すべてのメンバーを2進数のゼロに初期化し、次のステップでNumPutを頻繁に呼び出すのを避けるために通常使用します。
2)ターゲット関数が構造体の初期値を使用する場合は、NumPut("UInt", 123, MyStruct, 4)を呼び出して、0 以外の値を持つべきメンバーを初期化します。123をターゲットメンバに入れる整数に置き換えます(文字列のアドレスを格納する場合はStrPtr(Var)を指定します)。4を対象部材のオフセットに置き換える(「オフセット」の説明については手順4参照)。"UInt"を適切な型(メンバーがポインタまたはハンドルの場合は"Ptr"など)に置き換える。
3)MyStructをPtr引数として、ターゲット関数を呼び出す。例えば、DllCall("MyDll\MyFunc", "Ptr", MyStruct)となります。この機能は、メンバーの一部を検査したり、変更したりするものです。DllCallは自動的にバッファのアドレスを使用しますが、これは通常MyStruct.Ptrを使用して取得されます。
4)MyInteger := NumGet(MyStruct, 4, "UInt")を使って、構造体から任意の整数を取得します。4を構造体内の対象メンバーのオフセットに置き換える。最初のメンバーは常にオフセット0にあります。第2部材は、オフセット0に第1部材の大きさ(通常4)を加えた位置にある。2番目以降のメンバーは、前のメンバーのオフセットにサイズを足したものになります。DWORD、Intなどの32ビット整数のようなほとんどのメンバーは、4バイトのサイズです。"UInt"を適切な型に置き換えるか、メンバーがポインタまたはハンドルである場合は省略します。
実際の使用方法については、「構造例」を参照してください。
変数の文字列アドレス(StrPtr(MyVar)など)が関数に渡され、その関数が変数の内容の長さを変更した場合、その変数のその後の使用が正しく動作しないことがあります。この問題を解決するには、次のいずれかを行ってください:1)MyVarをPtr/アドレスとしてではなく、"Str"引数として渡す。2) DllCallを呼び出した後、VarSetStrCapacity(&MyVar, -1)を呼んで変数の内部に保存された長さを更新します。
関数によって変数に格納された2進数のゼロは、ターミネーターとして機能し、ほとんどの組み込み関数によってゼロの右側のすべてのデータがアクセスまたは変更されるのを防ぐことができます。しかし、このようなデータは、StrPtrで文字列のアドレスを取得し、NumPut、NumGet、StrGet、StrPut、DllCall自身など他の関数に渡すことで操作することができます。
渡された文字列のアドレスを返す関数が、期待とは異なるメモリーアドレスに同一の文字列を返すことがあります。例えば、プログラミング言語でCharLower(CharUpper(MyVar))を呼び出すと、MyVarの内容が小文字に変換されます。しかし、DllCallで同じことをすると、CharLowerがMyVarと同じ内容の別の/一時的な文字列を操作したため、次の呼び出しの後、MyVarは大文字になります:
MyVar := "ABC"
result := DllCall("CharLower", "Str", DllCall("CharUpper", "Str", MyVar, "Str"), "Str")
これを回避するには、上記の下線部の2つの "Str"の値をPtrに変更します。これは、CharUpperの戻り値を、CharLowerに整数として渡される純粋なアドレスと解釈します。
文字列を扱う場合、一定の制限が発生する場合があります。詳しくは、「バイナリ互換性」をご覧ください。
VBScriptや同様の言語でアクセス可能なCOMオブジェクトは、通常、ComObject、ComObjGet、ComObjActiveおよび組み込みオブジェクト構文によってAutoHotkeyでもアクセスできます。
IDispatchをサポートしていないCOMオブジェクトは、オブジェクトのインターフェースの仮想関数テーブルから関数のアドレスを取得することで、DllCallで使用できます。詳しくは、さらに下の例をご覧ください。しかし、通常はこのプロセスを合理化するComCallを使用するのがよいでしょう。
.NET Frameworkのライブラリは、Common Language Runtime(CLR)と呼ばれる「仮想マシン」によって実行されます。そのため、.NET DLLファイルは通常のDLLファイルとは異なるフォーマットになっており、一般的にDllCallが呼び出せるような関数は含まれていません。
しかし、AutoHotkeyは、COM呼び出し可能なラッパーを通してCLRを利用することができます。ライブラリが一般的なCOMコンポーネントとしても登録されていない限り、まずCLR自体をDllCallで手動で初期化する必要があります。For details, see .NET Framework Interop.
バイナリ互換性、Bufferオブジェクト、ComCall、PostMessage、OnMessage、CallbackCreate、Run、VarSetStrCapacity、関数、SysGet、#DllLoad、Windows API インデックス
Windows API関数 "MessageBox"を呼び出し、ユーザーがどのボタンを押したかを報告します。
WhichButton := DllCall("MessageBox", "Int", 0, "Str", "Press Yes or No", "Str", "Title of box", "Int", 4)
MsgBox "You pressed button #" WhichButton
デスクトップの壁紙を、指定したビットマップ(.bmp)ファイルに変更します。
DllCall("SystemParametersInfo", "UInt", 0x14, "UInt", 0, "Str", A_WinDir . "\winnt.bmp", "UInt", 1)
API関数 "IsWindowVisible"を呼び出し、メモ帳ウィンドウが表示されているかどうかを調べる。
DetectHiddenWindows True
if not DllCall("IsWindowVisible", "Ptr", WinExist("Untitled - Notepad")) ; WinExistはHWNDを返す。
MsgBox "The window is not visible."
APIのwsprintf()を呼び出し、数字432に先頭のゼロをパッドして10文字幅(0000000432)にします。
ZeroPaddedNumber := Buffer(20) ; バッファが新しい文字列を受け入れるのに十分な大きさであることを確認します。
DllCall("wsprintf", "Ptr", ZeroPaddedNumber, "Str", "%010d", "Int", 432, "Cdecl") ; Cdecl の呼び出し規約を必要とします。
MsgBox StrGet(ZeroPaddedNumber)
; または、Format関数とゼロフラグを組み合わせて使用します:
MsgBox Format("{:010}", 432)
A_TickCountの10 msより精度の高いQueryPerformanceCounter()のデモを行います。
DllCall("QueryPerformanceFrequency", "Int64*", &freq := 0)
DllCall("QueryPerformanceCounter", "Int64*", &CounterBefore := 0)
Sleep 1000
DllCall("QueryPerformanceCounter", "Int64*", &CounterAfter := 0)
MsgBox "Elapsed QPC time is " . (CounterAfter - CounterBefore) / freq * 1000 " ms"
ホットキーを押すと、マウスカーソルの速度が一時的に低下し、正確な位置決めがしやすくなります。F1を押し続けると、カーソルが遅くなる。離すと元の速度に戻ります。
F1::
F1 up::
{
static SPI_GETMOUSESPEED := 0x70
static SPI_SETMOUSESPEED := 0x71
static OrigMouseSpeed := 0
switch ThisHotkey
{
case "F1":
; 現在の速度を取得し、後で復元できるようにする:
DllCall("SystemParametersInfo", "UInt", SPI_GETMOUSESPEED, "UInt", 0, "Ptr*", &OrigMouseSpeed, "UInt", 0)
; ここで、マウスの速度を、最後から2番目のパラメータで指定された遅い速度に設定します(範囲は1~20、10がデフォルト):
DllCall("SystemParametersInfo", "UInt", SPI_SETMOUSESPEED, "UInt", 0, "Ptr", 3, "UInt", 0)
KeyWait "F1" ; キーボードのオートリピートがDllCallを繰り返し実行するのを防ぐことができます。
case "F1 up":
DllCall("SystemParametersInfo", "UInt", SPI_SETMOUSESPEED, "UInt", 0, "Ptr", OrigMouseSpeed, "UInt", 0) ; 元の速度に戻す。
}
}
アクティブなウィンドウを監視し、その垂直スクロールバーの位置をフォーカスコントロールに表示します(リアルタイムに更新されます)。
SetTimer WatchScrollBar, 100
WatchScrollBar()
{
FocusedHwnd := 0
try FocusedHwnd := ControlGetFocus("A")
if !FocusedHwnd ; フォーカスされたコントロールがない。
return
; 縦または横スクロールバーの位置をツールチップに表示する:
ToolTip DllCall("GetScrollPos", "Ptr", FocusedHwnd, "Int", 1) ; SB_VERTの場合は1、SB_HORZの場合は0になります。
}
ファイルにテキストを書き、それをメモリに読み戻す。この方法は、複数のファイルを同時に読み書きするような場合に、パフォーマンスを向上させるために使用することができます。また、FileOpenを使用しても同様の効果を得ることができます。
FileName := FileSelect("S16",, "Create a new file:")
if FileName = ""
return
GENERIC_WRITE := 0x40000000 ; 読み出しではなく、書き込みのためにファイルを開く。
CREATE_ALWAYS := 2 ; 新規ファイルを作成します(既存のファイルを上書きします)。
hFile := DllCall("CreateFile", "Str", FileName, "UInt", GENERIC_WRITE, "UInt", 0, "Ptr", 0, "UInt", CREATE_ALWAYS, "UInt", 0, "Ptr", 0, "Ptr")
if !hFile
{
MsgBox "Can't open '" FileName "' for writing."
return
}
TestString := "This is a test string.`r`n" ; この方法でファイルを書く場合、改行には `n ではなく `r`n を使用します。
StrSize := StrLen(TestString) * 2
DllCall("WriteFile", "Ptr", hFile, "Str", TestString, "UInt", StrSize, "UIntP", &BytesActuallyWritten := 0, "Ptr", 0)
DllCall("CloseHandle", "Ptr", hFile) ; ファイルを閉じる。
; ファイルが書き込まれたので、その内容をメモリに読み返してください。
GENERIC_READ := 0x80000000 ; 書き込みではなく、読み込みのためにファイルを開く。
OPEN_EXISTING := 3 ; このモードは、オープンするファイルが既に存在することを示します。
FILE_SHARE_READ := 0x1 ; こちらがファイルを開いている間に、他のプロセスがファイルを開くことができるかどうかです。
FILE_SHARE_WRITE := 0x2
hFile := DllCall("CreateFile", "Str", FileName, "UInt", GENERIC_READ, "UInt", FILE_SHARE_READ|FILE_SHARE_WRITE, "Ptr", 0, "UInt", OPEN_EXISTING, "UInt", 0, "Ptr", 0)
if !hFile
{
MsgBox "Can't open '" FileName "' for reading."
return
}
; 文字列を読み込むためのメモリブロックを確保する:
Buf := Buffer(StrSize)
DllCall("ReadFile", "Ptr", hFile, "Ptr", Buf, "UInt", Buf.Size, "UIntP", &BytesActuallyRead := 0, "Ptr", 0)
DllCall("CloseHandle", "Ptr", hFile) ; ファイルを閉じる。
MsgBox "The following string was read from the file: " StrGet(Buf)
Win+Cを押したときに、マウスカーソルを隠す。後でカーソルを表示させるには、このホットキーをもう一度押してください。
OnExit (*) => SystemCursor("Show") ; スクリプト終了時にカーソルが表示されるようにします。
#c::SystemCursor("Toggle") ; Win+CホットキーでカーソルのON/OFFを切り替えられます。
SystemCursor(cmd) ; cmd = "Show|Hide|Toggle|Reload"
{
static visible := true, c := Map()
static sys_cursors := [32512, 32513, 32514, 32515, 32516, 32642
, 32643, 32644, 32645, 32646, 32648, 32649, 32650]
if (cmd = "Reload" or !c.Count) ; リクエスト時またはファーストコール時にリロードします。
{
for i, id in sys_cursors
{
h_cursor := DllCall("LoadCursor", "Ptr", 0, "Ptr", id)
h_default := DllCall("CopyImage", "Ptr", h_cursor, "UInt", 2
, "Int", 0, "Int", 0, "UInt", 0)
h_blank := DllCall("CreateCursor", "Ptr", 0, "Int", 0, "Int", 0
, "Int", 32, "Int", 32
, "Ptr", Buffer(32*4, 0xFF)
, "Ptr", Buffer(32*4, 0))
c[id] := {default: h_default, blank: h_blank}
}
}
switch cmd
{
case "Show": visible := true
case "Hide": visible := false
case "Toggle": visible := !visible
default: return
}
for id, handles in c
{
h_cursor := DllCall("CopyImage"
, "Ptr", visible ? handles.default : handles.blank
, "UInt", 2, "Int", 0, "Int", 0, "UInt", 0)
DllCall("SetSystemCursor", "Ptr", h_cursor, "UInt", id)
}
}
構造例です。RECT構造体のアドレスをGetWindowRect()に渡すと、構造体のメンバーにウィンドウの左、上、右、下辺の位置(画面に対する相対位置)が設定されます。
Run "Notepad" WinWait "無題-メモ帳" ; これは、以下のWinExistで使用するための"last found window"も設定します。 Rect := Buffer(16) ; RECTは,4つの32ビット整数(4*4=16)からなる構造体である. DllCall("GetWindowRect", "Ptr", WinExist(), "Ptr", Rect) ; WinExistはHWNDを返す。 L := NumGet(Rect, 0, "Int"), T := NumGet(Rect, 4, "Int") R := NumGet(Rect, 8, "Int"), B := NumGet(Rect, 12, "Int") MsgBox Format("Left {1} Top {2} Right {3} Bottom {4}", L, T, R, B)
構造例です。FillRect()に、一時的に赤く塗る画面の一部を示すRECT構造体のアドレスを渡す。
Rect := Buffer(16) ; 4バイトの整数を4つ保持する容量を設定します。 NumPut( "Int", 0 ; 左 , "Int", 0 ; top , "Int", A_ScreenWidth//2 ; right , "Int", A_ScreenHeight//2 ; bottom , Rect) hDC := DllCall("GetDC", "Ptr", 0, "Ptr") ; デスクトップのデバイスコンテキストを取得する場合は、0を渡す。 hBrush := DllCall("CreateSolidBrush", "UInt", 0x0000FF, "Ptr") ; 赤のブラシ(0x0000FFはBGR形式)を作成します。 DllCall("FillRect", "Ptr", hDC, "Ptr", Rect, "Ptr", hBrush) ; 指定された矩形を上記のブラシで塗りつぶす。 DllCall("ReleaseDC", "Ptr", 0, "Ptr", hDC) ; クリーンアップ。 DllCall("DeleteObject", "Ptr", hBrush) ; クリーンアップ。
構造例です。システムの時計を指定した日付と時刻に変更します。未来の日付に変更すると、スケジュールされたタスクが早期に実行される可能性があるため、注意が必要です!
SetSystemTime("20051008142211") ; タイムスタンプを渡す(UTCではなくローカル)。
SetSystemTime(YYYYMMDDHHMISS)
; システムクロックを指定した日付と時刻に設定します。
; 呼び出し側は、入力されるパラメータが有効な日付-時間スタンプであることを確認する必要があります。
; (UTCではなく現地時間)。成功すれば0以外を、そうでなければ0を返す。
{
; SetSystemTime()で使用するため、パラメータをローカル時間からUTCに変換します。
UTC_Delta := DateDiff(A_Now, A_NowUTC, "Seconds") ; 四捨五入の関係で、「秒」の方が正確です。
UTC_Delta := Round(-UTC_Delta/60) ; 正確を期すため、分単位に丸めて表示します。
YYYYMMDDHHMISS := DateAdd(YYYYMMDDHHMISS, UTC_Delta, "Minutes") ; UTC に変換するためのオフセットを適用します。
SystemTime := Buffer(16) ; この構造体は8個のUShortで構成されています。
NumPut( "UShort", SubStr(YYYYMMDDHHMISS, 1, 4) ; YYYY (year)
, "UShort", SubStr(YYYYMMDDHHMISS, 5, 2) ; MM (month of year, 1-12)
, "UShort", 0 ; Unused (day of week)
, "UShort", SubStr(YYYYMMDDHHMISS, 7, 2) ; DD (day of month)
, "UShort", SubStr(YYYYMMDDHHMISS, 9, 2) ; HH (hour in 24-hour time)
, "UShort", SubStr(YYYYMMDDHHMISS, 11, 2) ; MI (minute)
, "UShort", SubStr(YYYYMMDDHHMISS, 13, 2) ; SS (second)
, "UShort", 0 ; Unused (millisecond)
, SystemTime)
return DllCall("SetSystemTime", "Ptr", SystemTime)
}
その他の構造例:
アクティブなウィンドウを3秒間、タスクバーから削除します。同等のComCallの例と比較してみてください。
/* ITaskbarListのVTableにあるメソッドです: IUnknown: 0 QueryInterface -- ComObjQueryの代わりに使用 1 AddRef -- ObjAddRefの代わりに使用 2 Release -- ObjReleaseの代わりに使用 ITaskbarList: 3 HrInit 4 AddTab 5 DeleteTab 6 ActivateTab 7 SetActiveAlt */ IID_ITaskbarList := "{56FDF342-FD6D-11d0-958A-006097C9A090}" CLSID_TaskbarList := "{56FDF344-FD6D-11d0-958A-006097C9A090}" ; TaskbarListオブジェクトを作成します。 tbl := ComObject(CLSID_TaskbarList, IID_ITaskbarList) activeHwnd := WinExist("A") DllCall(vtable(tbl.ptr,3), "ptr", tbl) ; tbl.HrInit() DllCall(vtable(tbl.ptr,5), "ptr", tbl, "ptr", activeHwnd) ; tbl.DeleteTab(activeHwnd) Sleep 3000 DllCall(vtable(tbl.ptr,4), "ptr", tbl, "ptr", activeHwnd) ; tbl.AddTab(activeHwnd) ; ラップされていないインターフェイスポインタは、手動で解放する必要があります。 ObjRelease(tbl.ptr) vtable(ptr, n) { ; NumGet(ptr, "ptr") は、オブジェクトの仮想関数のアドレスを返します。 ; テーブル(略してvtable)。この式の残りの部分は ; vtableからn番目の関数のアドレスを取得します。 return NumGet(NumGet(ptr, "ptr"), n*A_PtrSize, "ptr") }