Русский   English   中文

回调注册方法

此方法接受对脚本函数的引用,并将其转换为可以传递给 API 函数的指针。然后该 API 函数可以使用这个指针来调用脚本函数。例如,EnumWindows 需要这样一个指向回调函数的指针(参见下面的代码)。对于找到的每个窗口,它将调用回调函数,并将窗口句柄传递给它。如果回调过程返回 1,枚举继续,如果返回 0,枚举则停止。

脚本函数引用本身无法达到此目的,因为 JScript 和 VBScript 中的函数是对象,它们的引用是指向 IDispatch 接口的指针。因此,引用被传递给 RegisterCallback,API 函数接收到一个指向 dynwrapx 中的中间过程的指针,它将转换对脚本函数的调用,并将其返回值传回 API 函数。

在 JScript 中,函数名(不带括号)将用作其引用,而在 VBScript 中,您必须事先使用 GetRef。除了函数的引用之外,您可能还必须指定其参数类型(如果有)及其返回值 —— 就像使用 Register 方法一样(但只能使用小写字母)。

默认情况下,回调函数的调用约定为 stdcall,这对于 Windows API 来说是正常的。如果您使用的第三方 DLL 需要 C 调用约定 (cdecl) ,您可以在标志参数 ("f=c") 中指定它。

JScript
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 并将指针传递给回调过程。
DWX.EnumWindows(pCbkFunc, 0);

DWX.MemFree(Buf);

WScript.Echo("窗口总数:" + m + "\n带标题:" + n + "\n\n" + WinList);


// ................ 回调函数本身 .......................

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 并将指针传递给回调过程。
DWX.EnumWindows pCbkFunc, 0

DWX.MemFree Buf

WScript.Echo "窗口总数:" & m & vbCrLf & "带标题:" & n & _
              vbCrLf & vbCrLf & WinList


'................ 回调函数本身 .......................

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