</head> <body> <h1>RegisterCallback() <span class="ver">[v1.0.47+]</span></h1> <p>Creates a machine-code address that when called, redirects the call to a <a href="../Functions.htm">function</a> in the script.</p> <pre class="Syntax">Address := <span class="func">RegisterCallback</span>("FunctionName" <span class="optional">, Options := "", ParamCount := FormalCount, EventInfo := Address</span>)</pre> <h2 id="Parameters">Parâmetros</h2> <dl> <dt>Address</dt> <dd><p>Upon success, RegisterCallback() returns a numeric address that may be called by <a href="DllCall.htm">DllCall()</a> or anything else capable of calling a machine-code function. Upon failure, it returns an empty string. Failure occurs when <em>FunctionName</em>: 1) does not exist; 2) accepts too many or too few parameters according to <em>ParamCount</em>; or 3) accepts any <a href="../Functions.htm#ByRef">ByRef parameters</a>.</p></dd> <dt>FunctionName</dt> <dd> <p>A <a href="../Functions.htm">function</a>'s name, which must be enclosed in quotes if it is a literal string. This function is called automatically whenever <em>Address</em> is called. The function also receives the parameters that were passed to <em>Address</em>.</p> <p><span class="ver">[v1.1.06+]:</span> A <a href="Func.htm">function reference</a> can be passed instead of a function name.</p> </dd> <dt>Options</dt> <dd><p>Specify zero or more of the following words. Separate each option from the next with a space (e.g. <code>C Fast</code>).</p> <p id="Fast"><strong>Fast</strong> or <strong>F</strong>: Avoids starting a new <a href="../misc/Threads.htm">thread</a> each time <em>FunctionName</em> is called. Although this performs better, it must be avoided whenever the thread from which <em>Address</em> is called varies (e.g. when the callback is triggered by an incoming message). This is because <em>FunctionName</em> will be able to change global settings such as <a href="../misc/ErrorLevel.htm">ErrorLevel</a>, <a href="../Variables.htm#LastError">A_LastError</a>, and the <a href="../misc/WinTitle.htm#LastFoundWindow">last-found window</a> for whichever thread happens to be running at the time it is called. For more information, see <a href="#Threads">Remarks</a>.</p> <p><strong>CDecl</strong> or <strong>C</strong>: Makes <em>Address</em> conform to the "C" calling convention. This is typically omitted because the standard calling convention is much more common for callbacks.</p></dd> <dt>ParamCount</dt> <dd><p>The number of parameters that <em>Address</em>'s caller will pass to it. If entirely omitted, it defaults to the number of mandatory parameters in the <a href="../Functions.htm#define">definition</a> of <em>FunctionName</em>. In either case, ensure that the caller passes exactly this number of parameters.</p></dd> <dt>EventInfo</dt> <dd> <p>An integer that <em>FunctionName</em> will see in <a href="../Variables.htm#EventInfo">A_EventInfo</a> whenever it is called via this <em>Address</em>. This is useful when <em>FunctionName</em> is called by more than one <em>Address</em>. If omitted, it defaults to <em>Address</em>. Observação: Unlike other global settings, the <a href="../misc/Threads.htm">current thread</a>'s A_EventInfo is not disturbed by the <a href="#Fast">fast mode</a>.</p> <p>If the exe running the script is 32-bit, this parameter must be between 0 and 4294967295. If the exe is 64-bit, this parameter can be a 64-bit integer. Although <a href="../Variables.htm#EventInfo">A_EventInfo</a> usually returns an unsigned integer, AutoHotkey does not fully support unsigned 64-bit integers and therefore some operations may cause the value to wrap into the signed range.</p></dd> </dl> <h2 id="The_Callback_Functions_Parameters">The Callback Function's Parameters</h2> <p>A <a href="../Functions.htm">function</a> assigned to a callback address may accept up to 31 parameters. <a href="../Functions.htm#optional">Optional parameters</a> are permitted, which is useful when the function is called by more than one caller.</p> <p>Interpreting the parameters correctly requires some understanding of how the x86 calling conventions work. Since AutoHotkey does not have typed parameters, the callback's parameter list is assumed to consist of integers, and some reinterpretation may be required.</p> <p><strong>AutoHotkey 32-bit:</strong> All incoming parameters are unsigned 32-bit integers. Smaller types are padded out to 32 bits, while larger types are split into a series of 32-bit parameters.</p> <p>If an incoming parameter is intended to be a signed integer, any negative numbers can be revealed by following either of the following examples:</p> <pre><em>; Method #1</em> if (wParam &gt; 0x7FFFFFFF) wParam := -(~wParam) - 1 <em>; Method #2: Relies on the fact that AutoHotkey natively uses signed 64-bit integers.</em> wParam := wParam &lt;&lt; 32 &gt;&gt; 32</pre> <p><strong>AutoHotkey 64-bit:</strong> All incoming parameters are signed 64-bit integers. AutoHotkey does not natively support unsigned 64-bit integers. Smaller types are padded out to 64 bits, while larger types are always passed by address.</p> <p><strong>AutoHotkey 32-bit/64-bit:</strong> If an incoming parameter is intended to be 8-bit or 16-bit (or 32-bit on x64), the upper bits of the value might contain "garbage" which can be filtered out by using bitwise-and, as in the following examples:</p> <pre>Callback(UCharParam, UShortParam, UIntParam) { UCharParam &amp;= 0xFF UShortParam &amp;= 0xFFFF UIntParam &amp;= 0xFFFFFFFF <em>;...</em> }</pre> <p>If an incoming parameter is intended by its caller to be a string, what it actually receives is the address of the string. To retrieve the string itself, use <a href="StrGet.htm">StrGet()</a>:</p> <pre>MyString := StrGet(MyParameter) <em>; Requires <span class="ver">[AHK_L 46+]</span></em></pre> <p>If an incoming parameter is the address of a structure, the individual members may be extracted by following the steps at <a href="DllCall.htm#struct">DllCall structures</a>.</p> <p id="Indirect"><strong>Receiving parameters by address</strong> <span class="ver">[AHK_L 60+]</span>: If the function is declared as <a href="../Functions.htm#Variadic">variadic</a>, its final parameter is assigned the <i>address</i> of the first callback parameter which was not assigned to a script parameter. Por exemplo:</p> <pre> callback := RegisterCallback("TheFunc", "F", 3) <em>; Parameter list size must be specified.</em> TheFunc("TheFunc was called directly.") <em>; Call TheFunc directly.</em> DllCall(callback, "float", 10.5, "int64", 42) <em>; Call TheFunc via callback.</em> TheFunc(params*) { if IsObject(params) MsgBox % params[1] else MsgBox % <a href="NumGet.htm">NumGet</a>(params+0, "float") ", " NumGet(params+A_PtrSize, "int64") }</pre> <p>Most callbacks use the <em>stdcall</em> calling convention, which requires a fixed number of parameters. In those cases, <em>ParamCount</em> must be set to the size of the parameter list, where Int64 and Double count as two 32-bit parameters.</p> <p>With <em>Cdecl</em> or the 64-bit calling convention, <em>ParamCount</em> only affects how many script parameters are assigned values. If omitted, all optional parameters receive their default values and are excluded from the calculations for the address stored in <em>params</em>.</p> <h2 id="What_the_Function_Should_Return">What the Function Should <em>Return</em></h2> <p>If the function uses <a href="Return.htm">Return</a> 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, the function should return an integer, which is then returned to the caller. AutoHotkey 32-bit truncates return values to 32-bit, while AutoHotkey 64-bit supports 64-bit return values. Returning structs larger than this (by value) is not supported.</p> <h2 id="Threads">Fast vs. Slow</h2> <p>The default/slow mode causes the function to start off fresh with the default values for settings such as <a href="SendMode.htm">SendMode</a> and <a href="DetectHiddenWindows.htm">DetectHiddenWindows</a>. These defaults can be changed in the <a href="../Scripts.htm#auto">auto-execute section</a>.</p> <p>By contrast, the <a href="#Fast">fast mode</a> inherits global settings from whichever <a href="../misc/Threads.htm">thread</a> happens to be running at the time the function is called. Furthermore, any changes the function makes to global settings (including <a href="../misc/ErrorLevel.htm">ErrorLevel</a> and the <a href="../misc/WinTitle.htm#LastFoundWindow">last-found window</a>) will go into effect for the <a href="../misc/Threads.htm">current thread</a>. Consequently, the fast mode should be used only when it is known exactly which thread(s) the function will be called from.</p> <p>To avoid being interrupted by itself (or any other thread), a callback may use <a href="Critical.htm">Critical</a> as its first line. However, this is not completely effective when the function is called indirectly via the arrival of a message less than 0x0312 (increasing Critical's <a href="Critical.htm#Interval">interval</a> may help). Furthermore, <a href="Critical.htm">Critical</a> does not prevent the function from doing something that might indirectly result in a call to itself, such as calling <a href="PostMessage.htm">SendMessage</a> or <a href="DllCall.htm">DllCall()</a>.</p> <h2 id="Memory">Memory</h2> <p>Each use of RegisterCallback() allocates a small amount of memory (32 bytes plus system overhead). Since the OS frees this memory automatically when the script exits, any script that allocates a small, <em>fixed</em> number of callbacks does not have to explicitly free the memory. By contrast, a script that calls RegisterCallback() an indefinite/unlimited number of times should explicitly call the following on any unused callbacks:</p> <pre>DllCall("GlobalFree", "Ptr", Address, "Ptr")</pre> <h2 id="Related">Tópicos relacionados</h2> <p><a href="DllCall.htm">DllCall()</a>, <a href="OnMessage.htm">OnMessage()</a>, <a href="OnExit.htm#function">OnExit()</a>, <a href="OnExit.htm#command">OnExit</a>, <a href="OnClipboardChange.htm#function">OnClipboardChange()</a>, <a href="OnClipboardChange.htm#label">OnClipboardChange Label</a>, <a href="Sort.htm#callback">Sort's callback</a>, <a href="Critical.htm">Critical</a>, <a href="PostMessage.htm">Post/SendMessage</a>, <a href="../Functions.htm">Functions</a>, <a href="../misc/SendMessageList.htm">List of Windows Messages</a>, <a href="../misc/Threads.htm">Threads</a></p> <h2 id="Examples">Exemplos</h2> <div class="ex" id="ExWinList"> <p><a class="ex_number" href="#ExWinList"></a> Displays a summary of all top-level windows.</p> <pre><em>; For performance and memory conservation, call RegisterCallback() only once for a given callback:</em> if not EnumAddress <em>; Fast-mode is okay because it will be called only from this thread:</em> EnumAddress := RegisterCallback("EnumWindowsProc", "Fast") DetectHiddenWindows On <em>; Due to fast-mode, this setting will go into effect for the callback too.</em> <em>; Pass control to EnumWindows(), which calls the callback repeatedly:</em> DllCall("EnumWindows", "Ptr", EnumAddress, "Ptr", 0) MsgBox %Output% <em>; Display the information accumulated by the callback.</em> EnumWindowsProc(hwnd, lParam) { global Output WinGetTitle, title, ahk_id %hwnd% WinGetClass, class, ahk_id %hwnd% if title Output .= "HWND: " . hwnd . "`tTitle: " . title . "`tClass: " . class . "`n" return true <em>; Tell EnumWindows() to continue until all windows have been enumerated.</em> }</pre> </div> <div class="ex" id="ExSubclassGUI"> <p><a class="ex_number" href="#ExSubclassGUI"></a> Demonstrates how to subclass a GUI window by redirecting its WindowProc to a new WindowProc in the script. In this case, the background color of a text control is changed to a custom color.</p> <pre>TextBackgroundColor := 0xFFBBBB <em>; A custom color in BGR format.</em> TextBackgroundBrush := DllCall("CreateSolidBrush", "UInt", TextBackgroundColor) Gui, Add, Text, HwndMyTextHwnd, Here is some text that is given`na custom background color. Gui +LastFound GuiHwnd := WinExist() <em>; 64-bit scripts must call SetWindowLongPtr instead of SetWindowLong:</em> SetWindowLong := A_PtrSize=8 ? "SetWindowLongPtr" : "SetWindowLong" WindowProcNew := RegisterCallback("WindowProc", "" <em>; Specify "" to avoid fast-mode for subclassing.</em> , , MyTextHwnd) <em>; ParamCount can be omitted like this in <span class="ver">[v1.1.12+]</span>.</em> WindowProcOld := DllCall(SetWindowLong, "Ptr", GuiHwnd, "Int", -4 <em>; -4 is GWL_WNDPROC</em> , "Ptr", WindowProcNew, "Ptr") <em>; Return value must be set to Ptr or UPtr vs. Int.</em> Gui Show return WindowProc(hwnd, uMsg, wParam, lParam) { Critical global TextBackgroundColor, TextBackgroundBrush, WindowProcOld if (uMsg = 0x0138 &amp;&amp; lParam = A_EventInfo) <em>; 0x0138 is WM_CTLCOLORSTATIC.</em> { DllCall("SetBkColor", "Ptr", wParam, "UInt", TextBackgroundColor) return TextBackgroundBrush <em>; Return the HBRUSH to notify the OS that we altered the HDC.</em> } <em>; Otherwise (since above didn't return), pass all unhandled events to the original WindowProc.</em> return DllCall("CallWindowProc", "Ptr", WindowProcOld, "Ptr", hwnd, "UInt", uMsg, "Ptr", wParam, "Ptr", lParam) } GuiClose: ExitApp</pre> </div> </body> </html>