English   Главная

Метод 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