CallbackCreate

呼び出すと、スクリプト内の関数にリダイレクトされるマシンコードアドレスを作成します。

Address := CallbackCreate(Function , Options, ParamCount)

パラメータ

機能

型:機能オブジェクト

Addressが呼び出されるたびに自動的に呼び出される関数オブジェクトです。また、この関数はAddressに渡されたパラメータを受け取ります。

クロージャまたはバウンド関数は、同じスクリプト関数をすべて呼び出す複数のコールバックを区別するために使用することができます。

コールバックは関数オブジェクトへの参照を保持し、スクリプトがCallbackFreeを呼び出すとその参照を解放します。

Options

型:文字列

If blank or omitted, a new thread will be started each time Function is called, the standard calling convention will be used, and the parameters will be passed individually to Function. Otherwise, specify one or more of the following options. Separate each option from the next with a space (e.g. "C Fast").

Fast または F:Functionが呼び出されるたびに新しいスレッドを開始するのを避けることができます。この方が性能は良いのですが、Addressが呼び出されるスレッドが変化する場合(例えば、コールバックが着信メッセージによってトリガーされる場合)には、この方法は避けなければなりません。これは、Functionが呼び出された時にたまたま実行されていたスレッドのA_LastErrorlast-found windowなどのグローバル設定を変更することができるようになるためです。詳しくは、「備考」をご覧ください。

CDecl または C:Addressを"C "呼び出し規則に準拠させる。コールバックでは標準の呼び出し規約の方がはるかに一般的なので、これは通常省略されます。このオプションは、x64呼び出し規約を使用するAutoHotkeyの64ビットバージョンでは無視されます。

&: Causes the address of the parameter list (a single integer) to be passed to Function instead of the individual parameters. パラメータ値は、NumGetを用いて取得することができる。標準の32ビット呼び出し規約を使用する場合、ParamCountはパラメータリストのサイズをDWORD(バイト数を4で割った値)で指定する必要があります。

ParamCount

型:整数

If omitted, it defaults to Function.MinParams, which is usually the number of mandatory parameters in the definition of Function. Otherwise, specify the number of parameters that Address's caller will pass to it. いずれの場合も、呼び出し元が正確にこの数のパラメータを渡すことを確認します。

戻り値

型:整数

CallbackCreate は、マシンコード・アドレスを返す。このアドレスは通常、DllCallで外部関数に渡されるか、NumPutで構造体に入れられるが、DllCallで直接呼び出すことも可能です。CallbackFreeにアドレスを渡すと、コールバックが削除されます。

エラー処理

以下のいずれかの条件下で、この関数は失敗し、例外をスローします。

The Function's Parameters

コールバックアドレスに割り当てられた関数は、最大31個のパラメータを受け取ることができます。Optional parameters are permitted, which is useful when Function is called by more than one caller.

パラメータを正しく解釈するには、x86の呼び出し規約がどのように機能するかをある程度理解する必要があります。AutoHotkeyには型付きパラメータがないため、コールバックのパラメータリストは整数で構成されていると仮定され、いくつかの再解釈が必要となる場合があります。

AutoHotkey 32ビット:入力されるパラメータはすべて符号なし32ビット整数です。小さな型は32ビットにパディングされ、大きな型は32ビットの一連のパラメータに分割されます。

If an incoming parameter is intended to be a signed integer, any negative numbers can be revealed by following either of the following methods:

; 方法 #1
if (wParam > 0x7FFFFFFF)
    wParam := -(~wParam) - 1

; 方法 #2:AutoHotkeyがネイティブに符号付き64ビット整数を使用することに依存します。
wParam := wParam << 32 >> 32

AutoHotkey 64ビット:入力されるパラメータはすべて符号付き64ビット整数です。AutoHotkeyは、符号なし64ビット整数をネイティブでサポートしていません。小さい型は64ビットにパディングされ、大きい型は常にアドレスで渡されます。

AutoHotkey 32ビット/64ビット:入力されるパラメータが8ビットまたは16ビット(x64では32ビット)の場合、値の上位ビットに「ゴミ」が含まれることがありますが、次の例のようにビットワイズアンドを使用することでフィルタリングすることができます。

Callback(UCharParam, UShortParam, UIntParam) {
    UCharParam &= 0xFF
    UShortParam &= 0xFFFF
    UIntParam &= 0xFFFFFFFF
    ;...
}

入力されるパラメータが、呼び出し元によって文字列であることが意図されている場合、実際に受け取るのは文字列のアドレスです。文字列そのものを取得するには、StrGetを使用します。

MyString := StrGet(MyParameter)

入力されたパラメータが構造体のアドレスである場合、DllCall構造体の手順に従って、個々のメンバーを抽出することができます。

Receiving parameters by address: If the & option is used, Function receives the address of the first callback parameter. 事例:

callback := CallbackCreate(TheFunc, "F&", 3)  ; パラメータリストのサイズは32ビットで指定する必要があります。
DllCall(callback, "float", 10.5, "int64", 42)
TheFunc(params) {
    MsgBox NumGet(params, 0, "float") ", " NumGet(params, A_PtrSize, "int64")
}

32ビットプログラムのほとんどのコールバックは、固定数のパラメータを必要とするstdcall呼び出し規約を使用しています。その場合、ParamCountには、Int64とDoubleを2つの32ビットパラメータとしてカウントするパラメータリストのサイズを設定する必要があります。Cdeclまたは64ビット呼び出し規約では、ParamCountは何の効果もない。

What Function Should Return

If Function uses Return without any parameters, or it specifies a blank value such as "" (or it never uses Return at all), 0 is returned to the caller of the callback. Otherwise, Function should return an integer, which is then returned to the caller. AutoHotkey 32bitは戻り値を32bitに切り捨て、AutoHotkey 64bitは64bitの戻り値をサポートします。これより大きな構造体を(値で)返すことはサポートされていません。

高速と低速の比較

The default/slow mode causes Function to start off fresh with the default values for settings such as SendMode and DetectHiddenWindows. これらのデフォルトは、スクリプト起動時に変更することができます。

By contrast, the fast mode inherits global settings from whichever thread happens to be running at the time Function is called. Furthermore, any changes Function makes to global settings (including the last-found window) will go into effect for the current thread. Consequently, the fast mode should be used only when it is known exactly which thread(s) Function will be called from.

自分自身(あるいは他のスレッド)によって中断されるのを避けるために、コールバックはその最初の行としてCriticalを使用することができます。However, this is not completely effective when Function is called indirectly via the arrival of a message less than 0x0312 (increasing Critical's interval may help). Furthermore, Critical does not prevent Function from doing something that might indirectly result in a call to itself, such as calling SendMessage or DllCall.

CallbackFree

コールバックを削除し、関数オブジェクトへの参照を解放します。

CallbackFree(Address)

CallbackCreateを使用するたびに、少量のメモリ(32または48バイトとシステム・オーバーヘッド)が割り当てられる。OSはスクリプトの終了時にこのメモリを自動的に解放するので、少量の固定数のコールバックを割り当てるスクリプトであれば、明示的にメモリを解放しなくても大丈夫です。

しかし、コールバックが保持する関数オブジェクトが動的な性質を持つ場合(クロージャバインド関数など)、コールバックが不要になったときに解放することが特に重要になる場合があります。

DllCall, OnMessage, OnExit, OnClipboardChange, Sort's callback, Critical, PostMessage, SendMessage, Functions, Windows Messages, Threads

すべてのトップレベルウィンドウのサマリーを表示します。

EnumAddress := CallbackCreate(EnumWindowsProc, "Fast")  ; Fast-modeはこのスレッドからしか呼ばれないので大丈夫です。

DetectHiddenWindows True  ; 高速モードのため、この設定はコールバックにも有効になります。

; コールバックを繰り返し呼び出すEnumWindows()に制御を渡す。
DllCall("EnumWindows", "Ptr", EnumAddress, "Ptr", 0)
MsgBox Output  ; コールバックで蓄積された情報を表示します。
    
EnumWindowsProc(hwnd, lParam)
{
    global Output
    win_title := WinGetTitle(hwnd)
    win_class := WinGetClass(hwnd)
    if win_title
        Output .= "HWND:" hwnd "`tTitle:" win_title "`tClass:" win_class "`n"
    return true  ; EnumWindows() に、すべてのウィンドウが列挙されるまで続けるように指示します。
}

GUIウィンドウのWindowProcをスクリプト内の新しいWindowProcにリダイレクトして、サブクラス化する方法を示すものです。この場合、テキストコントロールの背景色はカスタムカラーに変更されます。

TextBackgroundColor := 0xFFBBBB  ; BGR 形式のカスタムカラー。
TextBackgroundBrush := DllCall("CreateSolidBrush", "UInt", TextBackgroundColor)

MyGui := Gui()
Text := MyGui.Add("Text",, "Here is some text that is given`na custom background color.")

; 64ビットスクリプトでは、SetWindowLongの代わりにSetWindowLongPtrを呼び出す必要があります。
SetWindowLong := A_PtrSize=8 ? "SetWindowLongPtr" : "SetWindowLong"

WindowProcNew := CallbackCreate(WindowProc)  ; サブクラス作成時のfast-modeは避けてください。
WindowProcOld := DllCall(SetWindowLong, "Ptr", MyGui.Hwnd, "Int", -4  ; -4 は GWL_WNDPROC
    , "Ptr", WindowProcNew, "Ptr") ; 戻り値は "Ptr "または "UPtr "対 "Int "に設定する必要があります。

MyGui.Show

WindowProc(hwnd, uMsg, wParam, lParam)
{
    Critical
    if (uMsg = 0x0138 && lParam = Text.Hwnd)  ; 0x0138 は WM_CTLCOLORSTATIC です。
    {
        DllCall("SetBkColor", "Ptr", wParam, "UInt", TextBackgroundColor)
        return TextBackgroundBrush  ; HDCを変更したことをOSに通知するため、HBRUSHを返す。
    }
    ; そうでない場合は(上記が返らなかったので)、処理されなかったすべてのイベントを元のWindowProcに渡します。
    return DllCall("CallWindowProc", "Ptr", WindowProcOld, "Ptr", hwnd, "UInt", uMsg, "Ptr", wParam, "Ptr", lParam)
}