Метод RegisterCallback
Этот метод нужен для получения указателя на скриптовую функцию, пригодного для передачи какой-либо функции API. Которая потом, используя этот указатель, могла бы данную скриптовую функцию вызывать. Пример такой API-функции — EnumWindows (см. код ниже). Она перебирает существующие окна и хэндл каждого окна передаёт callback-функции в качестве параметра. После этого она ждёт, что вернёт callback-функция. Если 1, то перебор идёт дальше, если 0 — прекращается.В JScript и VBScript функция является объектом, и ссылка на неё для таких целей не годится. Поэтому ссылка на скриптовую функцию сначала передаётся методу RegisterCallback, а API-функция получает возвращённый им указатель на одну из вспомогательных процедур внутри dynwrapx.dll, вызовы которой будут транслироваться в вызовы скриптовой функции, а возвращаемые значения — в обратном направлении.
В JScript ссылка на функцию — это её имя без скобок, а в VBScript сначала нужно использовать GetRef. Кроме ссылки на функцию задаются также типы её параметров и возвращаемого значения — аналогично методу Register (но используются только маленькие буквы).
По умолчанию соглашение вызова callback-функции будет stdcall, что подходит для Windows API. Если используется какая-то сторонняя библиотека, которой требуется соглашение вызова С (cdecl), это можно указать во флаговом параметре ("f=c").
Пример на JScript (VBScript см. ниже)
DWX = new ActiveXObject("DynamicWrapperX"); DWX.Register("user32", "EnumWindows", "i=ph"); DWX.Register("user32", "GetWindowTextW", "i=hpl"); // Unicode //DWX.Register("user32", "GetWindowText", "i=hpl"); // ANSI // Регистрация CbkEnumWin как функции обратного вызова // и получение указателя. pCbkFunc = DWX.RegisterCallback(CbkEnumWin, "i=hh", "r=l"); n=0, m=0, WinList=""; Buf = DWX.MemAlloc(256); // Буфер под заголовок окна (выходная строка). // Вызов EnumWindows с передачей ей указателя на callback-функцию. DWX.EnumWindows(pCbkFunc, 0); DWX.MemFree(Buf); WScript.Echo("Всего окон: " + m + "\nС заголовками: " + n + "\n\n" + WinList); // ............... Собственно callback-функция .................... function CbkEnumWin(hwnd, lparam) { var Title; DWX.GetWindowTextW(hwnd, Buf, 128); // Unicode Title = DWX.StrGet(Buf, "w"); //DWX.GetWindowText(hwnd, Buf, 256); // ANSI //Title = DWX.StrGet(Buf, "s"); if(Title.length > 0) { WinList += hwnd + "\t" + Title + "\n"; ++n; } ++m; return 1; // Если вернуть 0, вызовы прекратятся. }
Пример на VBScript
Set DWX = CreateObject("DynamicWrapperX") DWX.Register "user32", "EnumWindows", "i=ph" DWX.Register "user32", "GetWindowTextW", "i=hpl" ' Unicode 'DWX.Register "user32", "GetWindowText", "i=hpl" ' ANSI Set Ref = GetRef("CbkEnumWin") ' Получение ссылки на функцию. ' Регистрация CbkEnumWin как функции обратного вызова ' и получение указателя. pCbkFunc = DWX.RegisterCallback(Ref, "i=hh", "r=l") n = 0 : m = 0 : WinList = "" Buf = DWX.MemAlloc(256) ' Буфер под заголовок окна (выходная строка). ' Вызов EnumWindows с передачей ей указателя на callback-функцию. DWX.EnumWindows pCbkFunc, 0 DWX.MemFree Buf WScript.Echo "Всего окон: " & m & vbCrLf & "С заголовками: " & n & _ vbCrLf & vbCrLf & WinList ' ................ Собственно callback-функция ....................... Function CbkEnumWin(hwnd, lparam) DWX.GetWindowTextW hwnd, Buf, 128 ' Unicode Title = DWX.StrGet(Buf, "w") 'DWX.GetWindowText hwnd, Buf, 256 ' ANSI 'Title = DWX.StrGet(Buf, "s") If Len(Title) > 0 Then WinList = WinList & hwnd & vbTab & Title & vbCrLf n = n+1 End If m = m+1 CbkEnumWin = 1 ' Если вернуть 0, вызовы прекратятся. End Function