/
DllCall.htm
467 lines (419 loc) · 40.3 KB
/
DllCall.htm
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
<!DOCTYPE HTML>
<html lang="en">
<head>
<title>DllCall - Syntax & Usage | AutoHotkey v2</title>
<meta name="description" content="The DllCall function calls a function inside a DLL, such as a standard Windows API function." />
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<link href="../static/theme.css" rel="stylesheet" type="text/css" />
<script src="../static/content.js" type="text/javascript"></script>
</head>
<body>
<h1>DllCall</h1>
<p>Calls a function inside a DLL, such as a standard Windows API function.</p>
<pre class="Syntax">Result := <span class="func">DllCall</span>("<span class="optional">DllFile\</span>Function" <span class="optional">, Type1, Arg1, Type2, Arg2, "Cdecl ReturnType"</span>)</pre>
<h2 id="Parameters">Parameters</h2>
<dl>
<dt>[DllFile\]Function</dt>
<dd>
<p>Type: <a href="../Concepts.htm#strings">String</a> or <a href="../Concepts.htm#numbers">Integer</a></p>
<p>The DLL or EXE file name followed by a backslash and the name of the function. For example: <code>"MyDLL\MyFunction"</code> (the file extension ".dll" is the default when omitted). If an absolute path isn't specified, <em>DllFile</em> is assumed to be in the system's PATH or <a href="../Variables.htm#WorkingDir">A_WorkingDir</a>.</p>
<p id="std"><em>DllFile</em> may be omitted when calling a function that resides in User32.dll, Kernel32.dll, ComCtl32.dll, or Gdi32.dll. For example, <code>"User32\IsWindowVisible"</code> produces the same result as <code>"IsWindowVisible"</code>.</p>
<p>If no function can be found by the given name, a "W" (Unicode) suffix is automatically appended. For example, <code>"MessageBox"</code> is the same as <code>"MessageBoxW"</code>.</p>
<p>Performance can be dramatically improved when making <em>repeated</em> calls to a DLL by <a href="#load">loading it beforehand</a>.</p>
<p>This parameter may also consist solely of an integer, which is interpreted as the address of the function to call. Sources of such addresses include <a href="#COM">COM</a> and <a href="CallbackCreate.htm">CallbackCreate</a>.</p>
</dd>
<dt>Type1, Arg1</dt>
<dd>
<p>Type: <a href="../Concepts.htm#strings">String</a></p>
<p>Each of these pairs represents a single parameter to be passed to the function. The number of pairs is unlimited. For <em>Type</em>, see the <a href="#types">types table</a> below. For <em>Arg</em>, specify the value to be passed to the function.</p>
</dd>
<dt>Cdecl ReturnType</dt>
<dd>
<p>Type: <a href="../Concepts.htm#strings">String</a></p>
<p id="cdecl">The word <em>Cdecl</em> is normally omitted because most functions use the standard calling convention rather than the "C" calling convention (functions such as wsprintf that accept a varying number of arguments are one exception to this). Note that most object-oriented C++ functions use the <i>thiscall</i> convention, which is not supported.</p>
<p>If present, the word <em>Cdecl</em> should be listed before the return type (if any). Separate each word from the next with a space or tab. For example: <code>"Cdecl Str"</code>.</p>
<p>Since a separate "C" calling convention does not exist in 64-bit code, <i>Cdecl</i> may be specified but has no effect on 64-bit builds of AutoHotkey.</p>
<p><em>ReturnType</em>: If the function returns a 32-bit signed integer (Int), BOOL, or nothing at all, <em>ReturnType</em> may be omitted. Otherwise, specify one of the argument types from the <a href="#types">types table</a> below. The <a href="#asterisk">asterisk suffix</a> is also supported.</p>
</dd>
</dl>
<h2 id="Return_Value">Return Value</h2>
<p>Type: <a href="../Concepts.htm#strings">String</a> or <a href="../Concepts.htm#numbers">Integer</a></p>
<p>DllCall returns the actual value returned by <em>Function</em>. If <em>Function</em> is of a type that does not return a value, the result is an undefined value of the specified return type (integer by default).</p>
<h2 id="types">Types of Arguments and Return Values</h2>
<table class="info">
<tr>
<th>Type</th>
<th abbr="Descr">Description</th>
</tr>
<tr id="str">
<td>Str</td>
<td>
<p>A string such as <code>"Blue"</code> or <code>MyVar</code>, or a <a href="../Concepts.htm#variable-references">VarRef</a> such as <code>&MyVar</code>. If the called function modifies the string and the argument is a naked variable or VarRef, its contents will be updated. For example, the following call would convert the contents of <em>MyVar</em> to uppercase: <code>DllCall("CharUpper", "Str", <i>MyVar</i>)</code>.</p>
<p>If the function is designed to store a string longer than the parameter's input value (or if the parameter is for output only), the recommended approach is to use <a href="BufferAlloc.htm">BufferAlloc</a> to allocate a buffer, the <a href="#ptr">Ptr</a> type to pass it, and <a href="StrGet.htm">StrGet</a> to retrieve the string after the function returns. </p>
<p>Otherwise, ensure that the variable is large enough before calling the function. This can be achieved by calling <code><a href="VarSetStrCapacity.htm">VarSetStrCapacity</a>(MyVar, 123)</code>, where 123 is the number of 16-bit units (loosely referred to as characters) that <em>MyVar</em> must be able to hold. If the variable is not null-terminated upon return, an error message is shown and the program exits as it is likely that memory has been corrupted via buffer overrun. This would typically indicate that the variable's capacity was insufficient.</p>
<p>A <em>Str</em> argument must not be an <a href="../Variables.htm#Expressions">expression</a> that evaluates to a number (such as <code>i+1</code>). If it is, the function is not called and a <a href="../objects/Error.htm#TypeError">TypeError</a> is thrown.</p>
<p id="strp">The rarely-used <a href="#asterisk">Str*</a> arg type passes the address of a temporary variable containing the address of the string. If the function writes a new address into the temporary variable, the new string is copied into the script's variable, if a <a href="../Concepts.htm#variable-references">VarRef</a> was passed. This can be used with functions that expect something like "TCHAR **" or "LPTSTR *". However, if the function allocates memory and expects the caller to free it (such as by calling <a href="https://docs.microsoft.com/en-us/windows/win32/api/combaseapi/nf-combaseapi-cotaskmemfree">CoTaskMemFree</a>), the <code>Ptr*</code> arg type must be used instead.</p>
<p class="note"><strong>Note</strong>: When passing a string to a function, be aware what <a href="../Compat.htm#DllCall"><i>type</i> of string</a> the function expects.</p></td>
</tr>
<tr>
<td><span id="wstr"></span>WStr</td>
<td>Since AutoHotkey uses UTF-16 natively, WStr (wide character string) is equivalent to Str.</td>
</tr>
<tr>
<td><span id="astr"></span>AStr</td>
<td>
<p>AStr causes the input value to be automatically converted to ANSI. Since the temporary memory used for this conversion is only large enough for the converted input string, any value written to it by the function is discarded. To receive an ANSI string as an output parameter, follow this example:</p>
<pre>buf := BufferAlloc(<i>length</i>) <em>; Allocate temporary buffer.</em>
DllCall("<i>Function</i>", "ptr", buf) <em>; Pass buffer to function.</em>
str := StrGet(buf, "cp0") <em>; Retrieve ANSI string from buffer.</em>
</pre>
<p>The rarely-used <a href="#asterisk">AStr*</a> arg type is also supported and behaves similarly to the <a href="#strp">Str*</a> type, except that any new string is converted from ANSI to the native format, UTF-16.</p>
<p>See <a href="../Compat.htm#DllCall">Script Compatibility</a> for equivalent Win32 types and other details.</p>
</td>
</tr>
<tr>
<td>Int64</td>
<td>A 64-bit integer, whose range is -9223372036854775808 (-0x8000000000000000) to 9223372036854775807 (0x7FFFFFFFFFFFFFFF).</td>
</tr>
<tr id="Int">
<td>Int</td>
<td><p>A 32-bit integer (the most common integer type), whose range is -2147483648 (-0x80000000) to 2147483647 (0x7FFFFFFF). An Int is sometimes called a "Long".</p>
<p>An Int should also be used for each BOOL argument expected by a function (a BOOL value should be either 1 or 0).</p>
<p>An <a href="#unsigned">unsigned</a> Int (UInt) is also used quite frequently, such as for DWORD.</p></td>
</tr>
<tr>
<td>Short</td>
<td>A 16-bit integer, whose range is -32768 (-0x8000) to 32767 (0x7FFF). An <a href="#unsigned">unsigned</a> Short (UShort) can be used with functions that expect a WORD.</td>
</tr>
<tr>
<td>Char</td>
<td>An 8-bit integer, whose range is -128 (-0x80) to 127 (0x7F). An <a href="#unsigned">unsigned</a> character (UChar) can be used with functions that expect a BYTE.</td>
</tr>
<tr>
<td>Float</td>
<td>A 32-bit floating point number, which provides 6 digits of precision.</td>
</tr>
<tr>
<td>Double</td>
<td>A 64-bit floating point number, which provides 15 digits of precision.</td>
</tr>
<tr id="ptr">
<td>Ptr</td>
<td><p>A <a href="../Variables.htm#PtrSize">pointer-sized</a> integer, equivalent to Int or Int64 depending on whether the exe running the script is 32-bit or 64-bit. <i>Ptr</i> should be used for pointers to arrays or structures (such as RECT* or LPPOINT) and almost all handles (such as HWND, HBRUSH or HBITMAP). If the parameter is a pointer to a single numeric value such as LPDWORD or int*, generally the * or P suffix should be used instead of "Ptr".</p>
<p>If an object is passed to a Ptr parameter, the value of the object's <code>Ptr</code> property is used. If no such property exists, a <a href="../objects/Error.htm#PropertyError">PropertyError</a> is thrown. Typically the object would be a <a href="../objects/Buffer.htm">Buffer</a> object created by <a href="BufferAlloc.htm">BufferAlloc</a>.</p>
<p>If an object is passed to a Ptr* parameter, the value of the object's <code>Ptr</code> property is retrieved before the call and the address of a temporary variable containing this value is passed to the function. After the function returns, the new value is assigned back to the object's <code>Ptr</code> property.</p>
<p><i>Ptr</i> can also be used with the * or P suffix; it should be used with functions that output a pointer via LPVOID* or similar.</p>
<p><i>UPtr</i> is also valid, but is only unsigned in 32-bit builds as AutoHotkey does not support unsigned 64-bit integers.</p>
<p class="note"><strong>Note</strong>: To pass a <strong>NULL</strong> handle or pointer, pass the integer 0.</p></td>
</tr>
<tr id="asterisk">
<td>* or P<br>
(suffix)</td>
<td><p>Append an asterisk (with optional preceding space) to any of the above types to cause the address of the argument to be passed rather than the value itself (the called function must be designed to accept it). Since the value of such an argument might be modified by the function, whenever a <a href="../Concepts.htm#variable-references">VarRef</a> is passed as the argument, the variable's contents will be updated after the function returns. For example, the following call would pass the contents of MyVar to MyFunction by address, but would also update MyVar to reflect any changes made to it by MyFunction: <code>DllCall("MyDll\MyFunction", "Int*", &MyVar)</code>.</p>
<p>In general, an asterisk is used whenever a function has an argument type or return type that starts with "LP". The most common example is LPDWORD, which is a pointer to a DWORD. Since a DWORD is an unsigned 32-bit integer, use "UInt*" or "UIntP" to represent LPDWORD. An asterisk should not be used for string types such as LPTSTR, pointers to structures such as LPRECT, or arrays; for these, <a href="#str">"Str"</a> or <a href="#ptr">"Ptr"</a> should be used, depending on whether you pass a string, address or <a href="../objects/Buffer.htm">Buffer</a>.</p>
<p class="note"><strong>Note</strong>: "Char*" is not the same as <a href="#str">"Str"</a> because "Char*" passes the address of an 8-bit number, whereas <a href="#str">"Str"</a> passes the address of a series of characters, which may be either 16-bit (Unicode) or 8-bit (for "AStr"), depending on the version of AutoHotkey. Similarly, "UInt*" passes the address of a 32-bit number, so should not be used if the function expects an array of values or a structure larger than 32 bits.</p>
<p>Since variables in AutoHotkey have no fixed type, the address passed to the function points to temporary memory rather than the caller's variable.</p>
</td>
</tr>
<tr id="unsigned">
<td>U (prefix)</td>
<td><p>Prepend the letter U to any of the integer types above to interpret it as an unsigned integer (UInt64, UInt, UShort, and UChar). Strictly speaking, this is necessary only for return values and <a href="#asterisk">asterisk variables</a> because it does not matter whether an argument passed by value is unsigned or signed (except for Int64).</p>
<p>If a negative integer is specified for an unsigned argument, the integer wraps around into the unsigned domain. For example, when -1 is sent as a UInt, it would become 0xFFFFFFFF.</p>
<p><em>Unsigned</em> 64-bit integers produced by a function are not supported. Therefore, to work with numbers greater or equal to 0x8000000000000000, omit the U prefix and interpret any negative values received from the function as large integers. For example, a function that yields -1 as an Int64 is really yielding 0xFFFFFFFFFFFFFFFF if it is designed to yield a UInt64.</p>
</td>
</tr>
<tr id="HRESULT">
<td>HRESULT</td>
<td>
<p>A 32-bit integer. This is generally used with COM functions and is valid only as a return type without any prefix or suffix. Error values (as defined by the <a href="https://docs.microsoft.com/en-us/windows/win32/api/winerror/nf-winerror-failed">FAILED macro</a>) are never returned; instead, an <a href="../objects/Error.htm#OSError">OSError</a> is thrown. Therefore, the return value is a success code in the range 0 to 2147483647.</p>
<p>HRESULT is the default return type for <a href="ComCall.htm">ComCall</a>.</p>
</td>
</tr>
</table>
<h2 id="error">Errors</h2>
<p>DllCall throws an <a href="../objects/Error.htm">Error</a> under any of the following conditions:</p>
<ul>
<li><a href="../objects/Error.htm#OSError">OSError</a>: The <a href="#HRESULT">HRESULT</a> return type was used and the function returned an error value (as defined by the <a href="https://docs.microsoft.com/en-us/windows/win32/api/winerror/nf-winerror-failed">FAILED macro</a>). <code>Exception.Extra</code> contains the hexadecimal error code.</li>
<li><a href="../objects/Error.htm#TypeError">TypeError</a>: The <em>[DllFile\]Function</em> parameter is a floating point number. A string or positive integer is required.</li>
<li><a href="../objects/Error.htm#ValueError">ValueError</a>: The <a href="#types">return type</a> or one of the specified <a href="#types">arg types</a> is invalid.</li>
<li><a href="../objects/Error.htm#TypeError">TypeError</a>: An argument was passed a value of an unexpected type. For instance, an <a href="../Variables.htm#Expressions">expression</a> that evaluates to a number was passed to a string (<a href="#str">str</a>) argument, a non-numeric string was passed to a numeric argument, or an object was passed to an argument <em>not</em> of type <a href="#ptr">Ptr</a>.</li>
<li><a href="../objects/Error.htm">Error</a>: The specified <em>DllFile</em> could not be accessed or loaded. If no explicit path was specified for <em>DllFile</em>, the file must exist in the system's PATH or <a href="../Variables.htm#WorkingDir">A_WorkingDir</a>. This error might also occur if the user lacks permission to access the file, or if AutoHotkey is 32-bit and the DLL is 64-bit or vice versa.</li>
<li><a href="../objects/Error.htm">Error</a>: The specified function could not be found inside the DLL.</li>
<li><a href="../objects/Error.htm">Error</a>: The function was called but it aborted with a fatal exception. <code>Exception.Extra</code> contains the exception code. For example, 0xC0000005 means "access violation". In such cases, the thread is aborted (if <a href="Try.htm">try</a> is not used), but any <a href="#asterisk">asterisk variables</a> are still updated. An example of a fatal exception is dereferencing an invalid pointer such as NULL (0). Since a <a href="#cdecl">Cdecl</a> function never produces the error described in the next paragraph, it may generate an exception when too few arguments are passed to it.</li>
<li><a href="../objects/Error.htm">Error</a>: The function was called but was passed too many or too few arguments. <code>Exception.Extra</code> contains the number of bytes by which the argument list was incorrect. If it is positive, too many arguments (or arguments that were too large) were passed, or the call requires <a href="#cdecl">CDecl</a>. If it is negative, too few arguments were passed. This situation should be corrected to ensure reliable operation of the function. The presence of this error may also indicate that an exception occurred. Note that due to the x64 calling convention, 64-bit builds never raise this error.</li>
</ul>
<h2 id="except">Native Exceptions and A_LastError</h2>
<p>In spite of the built-in exception handling, it is still possible to crash a script with DllCall. This can happen when a function does not directly generate an exception but yields something inappropriate, such as a bad pointer or a string that is not terminated. This might not be the function's fault if the script passed it an unsuitable value such as a bad pointer or a <a href="#str">"str"</a> with insufficient capacity. A script can also crash when it specifies an inappropriate argument type or return type, such as claiming that an ordinary integer yielded by a function is an <a href="#asterisk">asterisk variable</a> or <a href="#str">str</a>.</p>
<p>The built-in variable <a href="../Variables.htm#LastError">A_LastError</a> contains the result of the operating system's GetLastError() function.</p>
<h2 id="load">Performance</h2>
<p>When making repeated calls to a DLL, performance can be dramatically improved by loading it explicitly (<em>this is not necessary for a <a href="#std">standard DLL</a> such as User32 because it is always resident</em>). This practice avoids the need for DllCall to internally call LoadLibrary and FreeLibrary each time. For example:</p>
<pre>hModule := DllCall("<strong>LoadLibrary</strong>", "Str", "MyFunctions.dll", "Ptr") <em>; Avoids the need for DllCall in the loop to load the library.</em>
Loop Files, "C:\My Documents\*.*", "R"
result := DllCall("MyFunctions\BackupFile", "Str", A_LoopFilePath)
DllCall("<strong>FreeLibrary</strong>", "Ptr", hModule) <em>; To conserve memory, the DLL may be unloaded after using it.</em></pre>
<p>Even faster performance can be achieved by looking up the function's address beforehand. For example:</p>
<pre><em>; In the following example, if the DLL isn't yet loaded, use LoadLibrary in place of GetModuleHandle.</em>
<strong>MulDivProc</strong> := DllCall("GetProcAddress", "Ptr", DllCall("GetModuleHandle", "Str", "<strong>kernel32</strong>", "Ptr"), "AStr", "<strong>MulDiv</strong>", "Ptr")
Loop 500
DllCall(<strong>MulDivProc</strong>, "Int", 3, "Int", 4, "Int", 3)</pre>
<p>If DllCall's first parameter is a literal string such as <code>"MulDiv"</code> and the DLL containing the function is ordinarily loaded before the script starts, or has been successfully loaded with <a href="_DllLoad.htm">#DllLoad</a>, the string is automatically resolved to a function address. This built-in optimization is more effective than the example shown above.</p>
<p>Finally, when passing a string-variable to a function that will not change the length of the string, performance is improved by passing the variable <a href="StrPtr.htm">by address</a> (e.g. <code>StrPtr(MyVar)</code>) rather than as a "<a href="#str">str</a>" (especially when the string is very long). The following example converts a string to uppercase: <code>DllCall("CharUpper", "<strong>Ptr</strong>", StrPtr(MyVar), "Ptr")</code>.</p>
<h2 id="struct">Structures and Arrays</h2>
<p>A structure is a collection of <em>members</em> (fields) stored adjacently in memory. Most members tend to be integers.</p>
<p>Functions that accept the address of a structure (or a memory-block array) can be called by allocating memory by some means and passing the memory address to the function. The <a href="BufferAlloc.htm">BufferAlloc</a> function and <a href="../objects/Buffer.htm">Buffer</a> object are recommended for this purpose. The following steps are generally used:</p>
<p>1) Call <code>MyStruct := BufferAlloc(123, 0)</code> to allocate a buffer to hold the structure's data. Replace <code>123</code> with a number that is at least as large as the size of the structure, in bytes. Specifying zero as the last parameter is optional; it initializes all members to be binary zero, which is typically used to avoid calling NumPut as often in the next step.</p>
<p>2) If the target function uses the values initially in the structure, call <code><a href="NumPut.htm">NumPut</a>("UInt", 123, MyStruct, 4)</code> to initialize any members that should be non-zero. Replace <code>123</code> with the integer to be put into the target member (or specify <code>StrPtr(Var)</code> to store the address of a string). Replace <code>4</code> with the offset of the target member (see step #4 for description of "offset"). Replace <code>"UInt"</code> with the appropriate type, such as <code>"Ptr"</code> if the member is a pointer or handle.</p>
<p>3) Call the target function, passing <em>MyStruct</em> as a Ptr argument. For example, <code>DllCall("MyDll\MyFunc", "Ptr", MyStruct)</code>. The function will examine and/or change some of the members. DllCall automatically uses the address of the buffer, which is normally retrieved by using <code>MyStruct.Ptr</code>.</p>
<p>4) Use <code>MyInteger := <a href="NumGet.htm">NumGet</a>(MyStruct, 4, "UInt")</code> to retrieve any desired integers from the structure. Replace <code>4</code> with the offset of the target member in the structure. The first member is always at offset 0. The second member is at offset 0 plus the size of the first member (typically 4). Members beyond the second are at the offset of the previous member plus the size of the previous member. Most members -- such as DWORD, Int, and <a href="#Int">other types of 32-bit integers</a> -- are 4 bytes in size. Replace <code>"UInt"</code> with the appropriate type or omit it if the member is a pointer or handle.</p>
<p>See <a href="#ExStruct">Structure Examples</a> for actual usages.</p>
<h2 id="limits">Known Limitations</h2>
<p>When a variable's string address (e.g. <code>StrPtr(MyVar)</code>) is passed to a function and that function alters the length of the variable's contents, subsequent uses of the variable may behave incorrectly. To fix this, do one of the following: 1) Pass <em>MyVar</em> as a <a href="#str">"Str"</a> argument rather than as a Ptr/address; 2) Call <code><a href="VarSetStrCapacity.htm#neg1">VarSetStrCapacity</a>(MyVar, -1)</code> to update the variable's internally-stored length after calling DllCall.</p>
<p>Any binary zero stored in a variable by a function may act as a terminator, preventing all data to the right of the zero from being accessed or changed by most built-in functions. However, such data can be manipulated by retrieving the string's address with <a href="StrPtr.htm">StrPtr</a> and passing it to other functions, such as <a href="NumPut.htm">NumPut</a>, <a href="NumGet.htm">NumGet</a>, <a href="StrGet.htm">StrGet</a>, <a href="StrPut.htm">StrPut</a>, and DllCall itself.</p>
<p>A function that returns the address of one of the strings that was passed into it might return an identical string in a different memory address than expected. For example calling <code>CharLower(CharUpper(MyVar))</code> in a programming language would convert <em>MyVar</em>'s contents to lowercase. But when the same is done with DllCall, <em>MyVar</em> would be uppercase after the following call because CharLower would have operated on a different/temporary string whose contents were identical to <em>MyVar</em>:</p>
<pre>MyVar := "ABC"
result := DllCall("CharLower", "<strong><u>Str</u></strong>", DllCall("CharUpper", "Str", MyVar, "<strong><u>Str</u></strong>"), "Str")</pre>
<p>To work around this, change the two underlined "Str" values above to Ptr. This interprets CharUpper's return value as a pure address that will get passed as an integer to CharLower.</p>
<p>Certain limitations may be encountered when dealing with strings. For details, see <a href="../Compat.htm#DllCall">Script Compatibility</a>.</p>
<h2 id="COM">Component Object Model (COM)</h2>
<p>COM objects which are accessible to VBScript and similar languages are typically also accessible to AutoHotkey via <a href="ComObjCreate.htm">ComObjCreate</a>, <a href="ComObjGet.htm">ComObjGet</a> or <a href="ComObjActive.htm">ComObjActive</a> and the built-in <a href="../Objects.htm#Usage_Objects">object syntax</a>.</p>
<p>COM objects which don't support <a href="http://msdn.microsoft.com/en-us/library/ms221608.aspx">IDispatch</a> can be used with DllCall by retrieving the address of a function from the virtual function table of the object's interface. For more details, see <a href="#ExTaskbar">the example</a> further below. However, it is usually better to use <a href="ComCall.htm">ComCall</a>, which streamlines this process.</p>
<h2 id="dotnet">.NET Framework</h2>
<p>.NET Framework libraries are executed by a "virtual machine" known as the Common Language Runtime, or CLR. That being the case, .NET DLL files are formatted differently to normal DLL files, and generally do not contain any functions which DllCall is capable of calling.</p>
<p>However, AutoHotkey can utilize the CLR through <a href="https://docs.microsoft.com/en-us/dotnet/standard/native-interop/com-callable-wrapper">COM callable wrappers</a>. Unless the library is also registered as a general COM component, the CLR itself must first be manually initialized via DllCall. For details, see <a href="https://www.autohotkey.com/forum/topic26191.html">.NET Framework Interop</a> (which currently utilizes DllCall and is not compatible with AutoHotkey v2).</p>
<h2 id="Related">Related</h2>
<p><a href="../Compat.htm#DllCall">Script Compatibility</a>, <a href="BufferAlloc.htm">BufferAlloc</a>, <a href="../objects/Buffer.htm">Buffer object</a>, <a href="ComCall.htm">ComCall</a>, <a href="PostMessage.htm">PostMessage</a>, <a href="OnMessage.htm">OnMessage</a>, <a href="CallbackCreate.htm">CallbackCreate</a>, <a href="Run.htm">Run</a>, <a href="VarSetStrCapacity.htm">VarSetStrCapacity</a>, <a href="../Functions.htm">Functions</a>, <a href="SysGet.htm">SysGet</a>, <a href="_DllLoad.htm">#DllLoad</a>, <a href="https://docs.microsoft.com/en-au/windows/win32/apiindex/windows-api-list">Windows API Index</a></p>
<h2 id="Examples">Examples</h2>
<div class="ex" id="ExMessageBox">
<p><a class="ex_number" href="#ExMessageBox"></a> Calls the Windows API function "MessageBox" and reports which button the user presses.</p>
<pre>WhichButton := DllCall("MessageBox", "Int", 0, "Str", "Press Yes or No", "Str", "Title of box", "Int", 4)
MsgBox "You pressed button #" WhichButton</pre>
</div>
<div class="ex" id="ExWallpaper">
<p><a class="ex_number" href="#ExWallpaper"></a> Changes the desktop wallpaper to the specified bitmap (.bmp) file.</p>
<pre>DllCall("SystemParametersInfo", "UInt", 0x14, "UInt", 0, "Str", A_WinDir <strong>.</strong> "\winnt.bmp", "UInt", 1)</pre>
</div>
<div class="ex" id="ExIsWindowVisible">
<p><a class="ex_number" href="#ExIsWindowVisible"></a> Calls the API function "IsWindowVisible" to find out if a Notepad window is visible.</p>
<pre>DetectHiddenWindows True
if not DllCall("IsWindowVisible", "Ptr", WinExist("Untitled - Notepad")) <em>; WinExist returns an HWND.</em>
MsgBox "The window is not visible."</pre>
</div>
<div class="ex" id="ExWsprintf">
<p><a class="ex_number" href="#ExWsprintf"></a> Calls the API's wsprintf() to pad the number 432 with leading zeros to make it 10 characters wide (0000000432).</p>
<pre>ZeroPaddedNumber := BufferAlloc(20) <em>; Ensure the buffer is large enough to accept the new string.</em>
DllCall("wsprintf", "Ptr", ZeroPaddedNumber, "Str", "%010d", "Int", 432, "Cdecl") <em>; Requires the Cdecl calling convention.</em>
MsgBox StrGet(ZeroPaddedNumber)
<em>; Alternatively, use the <a href="Format.htm">Format</a> function in conjunction with the zero flag:</em>
MsgBox Format("{:010}", 432)
</pre>
</div>
<div class="ex" id="ExQPC">
<p><a class="ex_number" href="#ExQPC"></a> Demonstrates QueryPerformanceCounter(), which gives more precision than <a href="../Variables.htm#TickCount">A_TickCount</a>'s 10ms.</p>
<pre>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"</pre>
</div>
<div class="ex" id="ExMouseSpeed">
<p><a class="ex_number" href="#ExMouseSpeed"></a> Press a hotkey to temporarily reduce the mouse cursor's speed, which facilitates precise positioning. Hold down <kbd>F1</kbd> to slow down the cursor. Release it to return to original speed.</p>
<pre>
F1::
F1 up::
{
static SPI_GETMOUSESPEED := 0x70
static SPI_SETMOUSESPEED := 0x71
static OrigMouseSpeed := 0
switch ThisHotkey
{
case "F1":
<em>; Retrieve the current speed so that it can be restored later:</em>
DllCall("SystemParametersInfo", "UInt", SPI_GETMOUSESPEED, "UInt", 0, "Ptr*", OrigMouseSpeed, "UInt", 0)
<em>; Now set the mouse to the slower speed specified in the next-to-last parameter (the range is 1-20, 10 is default):</em>
DllCall("SystemParametersInfo", "UInt", SPI_SETMOUSESPEED, "UInt", 0, "Ptr", 3, "UInt", 0)
KeyWait "F1" <em>; This prevents keyboard auto-repeat from doing the DllCall repeatedly.</em>
case "F1 up":
DllCall("SystemParametersInfo", "UInt", SPI_SETMOUSESPEED, "UInt", 0, "Ptr", OrigMouseSpeed, "UInt", 0) <em>; Restore the original speed.</em>
}
}</pre>
</div>
<div class="ex" id="ExWatchScrollBar">
<p><a class="ex_number" href="#ExWatchScrollBar"></a> Monitors the active window and displays the position of its vertical scroll bar in its focused control (with real-time updates).</p>
<pre>SetTimer WatchScrollBar, 100
WatchScrollBar()
{
FocusedHwnd := 0
try FocusedHwnd := ControlGetFocus("A")
if !FocusedHwnd <em>; No focused control.</em>
return
<em>; Display the vertical or horizontal scroll bar's position in a tooltip:</em>
ToolTip DllCall("GetScrollPos", "Ptr", FocusedHwnd, "Int", 1) <em>; Last parameter is 1 for SB_VERT, 0 for SB_HORZ.</em>
}</pre>
</div>
<div class="ex" id="ExFile">
<p><a class="ex_number" href="#ExFile"></a> Writes some text to a file then reads it back into memory. This method can be used to help performance in cases where multiple files are being read or written simultaneously. Alternatively, <a href="FileOpen.htm">FileOpen</a> can be used to achieve the <a href="FileOpen.htm#ExWriteRead">same effect</a>.</p>
<pre>
FileName := FileSelect("S16",, "Create a new file:")
if FileName = ""
return
GENERIC_WRITE := 0x40000000 <em>; Open the file for writing rather than reading.</em>
CREATE_ALWAYS := 2 <em>; Create new file (overwriting any existing file).</em>
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" <em>; When writing a file this way, use `r`n rather than `n to start a new line.</em>
StrSize := StrLen(TestString) * 2
DllCall("WriteFile", "Ptr", hFile, "Str", TestString, "UInt", StrSize, "UIntP", BytesActuallyWritten := 0, "Ptr", 0)
DllCall("CloseHandle", "Ptr", hFile) <em>; Close the file.</em>
<em>; Now that the file was written, read its contents back into memory.</em>
GENERIC_READ := 0x80000000 <em>; Open the file for reading rather than writing.</em>
OPEN_EXISTING := 3 <em>; This mode indicates that the file to be opened must already exist.</em>
FILE_SHARE_READ := 0x1 <em>; This and the next are whether other processes can open the file while we have it open.</em>
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
}
<em>; Allocate a block of memory for the string to read:</em>
Buf := BufferAlloc(StrSize)
DllCall("ReadFile", "Ptr", hFile, "Ptr", Buf, "UInt", Buf.Size, "UIntP", BytesActuallyRead := 0, "Ptr", 0)
DllCall("CloseHandle", "Ptr", hFile) <em>; Close the file.</em>
MsgBox "The following string was read from the file: " StrGet(Buf)</pre>
</div>
<div class="ex" id="ExHideCursor">
<p><a class="ex_number" href="#ExHideCursor"></a> Hides the mouse cursor when you press <kbd>Win</kbd>+<kbd>C</kbd>. To later show the cursor, press this hotkey again.</p>
<pre>OnExit (*) => SystemCursor("Show") <em>; Ensure the cursor is made visible when the script exits.</em>
#c::SystemCursor("Toggle") <em>; Win+C hotkey to toggle the cursor on and off.</em>
SystemCursor(cmd) <em>; cmd = "Show|Hide|Toggle|Reload"</em>
{
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) <em>; Reload when requested or at first call.</em>
{
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", BufferAlloc(32*4, 0xFF)
, "Ptr", BufferAlloc(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)
}
}</pre>
</div>
<div class="ex" id="ExStruct">
<p><a class="ex_number" href="#ExStruct"></a> Structure example. Pass the address of a RECT structure to GetWindowRect(), which sets the structure's members to the positions of the left, top, right, and bottom sides of a window (relative to the screen).</p>
<pre>Run "Notepad"
WinWait "Untitled - Notepad" <em>; This also sets the "<a href="../misc/WinTitle.htm#LastFoundWindow">last found window</a>" for use with WinExist below.</em>
Rect := BufferAlloc(16) <em>; A RECT is a struct consisting of four 32-bit integers (i.e. 4*4=16).</em>
DllCall("GetWindowRect", "Ptr", WinExist(), "Ptr", Rect) <em>; WinExist returns an HWND.</em>
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)</pre>
</div>
<div class="ex" id="ExStructRect">
<p><a class="ex_number" href="#ExStructRect"></a> Structure example. Pass to FillRect() the address of a RECT structure that indicates a part of the screen to temporarily paint red.</p>
<pre>Rect := BufferAlloc(16) <em>; Set capacity to hold four 4-byte integers.</em>
<a href="NumPut.htm">NumPut</a>( "Int", 0 <em>; left</em>
, "Int", 0 <em>; top</em>
, "Int", A_ScreenWidth//2 <em>; right</em>
, "Int", A_ScreenHeight//2 <em>; bottom</em>
, Rect)
hDC := DllCall("GetDC", "Ptr", 0, "Ptr") <em>; Pass zero to get the desktop's device context.</em>
hBrush := DllCall("CreateSolidBrush", "UInt", 0x0000FF, "Ptr") <em>; Create a red brush (0x0000FF is in BGR format).</em>
DllCall("FillRect", "Ptr", hDC, "Ptr", Rect, "Ptr", hBrush) <em>; Fill the specified rectangle using the brush above.</em>
DllCall("ReleaseDC", "Ptr", 0, "Ptr", hDC) <em>; Clean-up.</em>
DllCall("DeleteObject", "Ptr", hBrush) <em>; Clean-up.</em></pre>
</div>
<div class="ex" id="ExSystemTime">
<p><a class="ex_number" href="#ExSystemTime"></a> Structure example. Changes the system's clock to the specified date and time. Use caution when changing to a date in the future as it may cause scheduled tasks to run prematurely!</p>
<pre>SetSystemTime("20051008142211") <em>; Pass it a <a href="FileSetTime.htm#YYYYMMDD">timestamp</a> (local, not UTC).</em>
SetSystemTime(YYYYMMDDHHMISS)
<em>; Sets the system clock to the specified date and time.
; Caller must ensure that the incoming parameter is a valid date-time stamp
; (local time, not UTC). Returns non-zero upon success and zero otherwise.</em>
{
<em>; Convert the parameter from local time to UTC for use with SetSystemTime().</em>
UTC_Delta := DateDiff(A_Now, A_NowUTC, "Seconds") <em>; Seconds is more accurate due to rounding issue.</em>
UTC_Delta := Round(-UTC_Delta/60) <em>; Round to nearest minute to ensure accuracy.</em>
YYYYMMDDHHMISS := DateAdd(YYYYMMDDHHMISS, UTC_Delta, "Minutes") <em>; Apply offset to convert to UTC.</em>
SystemTime := BufferAlloc(16) <em>; This struct consists of 8 UShorts (i.e. 8*2=16).</em>
<a href="NumPut.htm">NumPut</a>( "UShort", SubStr(YYYYMMDDHHMISS, 1, 4) <em>; YYYY (year)</em>
, "UShort", SubStr(YYYYMMDDHHMISS, 5, 2) <em>; MM (month of year, 1-12)</em>
, "UShort", 0 <em>; Unused (day of week)</em>
, "UShort", SubStr(YYYYMMDDHHMISS, 7, 2) <em>; DD (day of month)</em>
, "UShort", SubStr(YYYYMMDDHHMISS, 9, 2) <em>; HH (hour in 24-hour time)</em>
, "UShort", SubStr(YYYYMMDDHHMISS, 11, 2) <em>; MI (minute)</em>
, "UShort", SubStr(YYYYMMDDHHMISS, 13, 2) <em>; SS (second)</em>
, "UShort", 0 <em>; Unused (millisecond)</em>
, SystemTime)
return DllCall("SetSystemTime", "Ptr", SystemTime)
}</pre>
<p>More structure examples:</p>
<ul>
<li>See the <a href="../scripts/index.htm#WinLIRC">WinLIRC client script</a> for a demonstration of how to use DllCall to make a network connection
to a TCP/IP server and receive data from it.</li>
<li>The operating system offers standard dialog boxes that prompt the user to pick a font and/or color, or an icon.
These dialogs use structures and are demonstrated at <a href="https://github.com/majkinetor/mm-autohotkey/tree/master/Dlg">GitHub</a>.</li>
</ul>
</div>
<div class="ex" id="ExTaskbar">
<p><a class="ex_number" href="#ExTaskbar"></a> Removes the active window from the taskbar for 3 seconds. Compare this to the <a href="ComCall.htm#ExTaskbar">equivalent ComCall example</a>.</p>
<pre><em>/*
Methods in <a href="http://msdn.microsoft.com/en-us/library/bb774652.aspx">ITaskbarList</a>'s VTable:
IUnknown:
0 QueryInterface -- use <a href="ComObjQuery.htm">ComObjQuery</a> instead
1 AddRef -- use <a href="ObjAddRef.htm">ObjAddRef</a> instead
2 Release -- use <a href="ObjAddRef.htm">ObjRelease</a> instead
ITaskbarList:
3 HrInit
4 AddTab
5 DeleteTab
6 ActivateTab
7 SetActiveAlt
*/</em>
IID_ITaskbarList := "{56FDF342-FD6D-11d0-958A-006097C9A090}"
CLSID_TaskbarList := "{56FDF344-FD6D-11d0-958A-006097C9A090}"
<em>; Create the TaskbarList object.</em>
tbl := <a href="ComObjCreate.htm">ComObjCreate</a>(CLSID_TaskbarList, IID_ITaskbarList)
activeHwnd := WinExist("A")
DllCall(vtable(tbl.ptr,3), "ptr", tbl) <em>; tbl.<a href="http://msdn.microsoft.com/en-us/library/bb774650.aspx">HrInit</a>()</em>
DllCall(vtable(tbl.ptr,5), "ptr", tbl, "ptr", activeHwnd) <em>; tbl.<a href="http://msdn.microsoft.com/en-us/library/bb774648.aspx">DeleteTab</a>(activeHwnd)</em>
Sleep 3000
DllCall(vtable(tbl.ptr,4), "ptr", tbl, "ptr", activeHwnd) <em>; tbl.<a href="http://msdn.microsoft.com/en-us/library/bb774646.aspx">AddTab</a>(activeHwnd)</em>
<em>; Non-wrapped interface pointers must be manually freed.</em>
ObjRelease(tbl.ptr)
vtable(ptr, n) {
<em>; NumGet(ptr, "ptr") returns the address of the object's virtual function
; table (vtable for short). The remainder of the expression retrieves
; the address of the nth function's address from the vtable.</em>
return NumGet(NumGet(ptr, "ptr"), n*A_PtrSize, "ptr")
}
</pre>
</div>
</body>
</html>