如何实现回调函数

以下过程和示例演示托管应用程序如何使用平台调用在本地计算机上打印每个窗口的句柄值。 具体而言,该过程和示例使用 EnumWindows 函数遍历窗口列表,并利用一个名为 CallBack 的托管回调函数来打印窗口句柄的值。

实现回调函数

  1. 在进一步执行实现之前,请查看函数的 EnumWindows 签名。 EnumWindows 具有以下签名:

    BOOL EnumWindows(WNDENUMPROC lpEnumFunc, LPARAM lParam)
    

    此函数需要回调的一个线索是lpEnumFunc参数的存在。 通常可以看到 lp(长指针)前缀与 Func 后缀结合使用在接受指向回调函数的指针的参数名称中。 有关 Win32 函数的文档,请参阅Microsoft平台 SDK。

  2. 创建托管回调函数。 该示例声明一个委托类型(调用 CallBack),该类型采用两个参数(hwndlparam)。 第一个参数是窗口的句柄;第二个参数是应用程序定义的。 在此版本中,这两个参数必须是整数。

    回调函数通常返回非零值来指示成功,零表示失败。 此示例显式设置返回值 true 以继续枚举。

  3. 创建一个委托,并将它作为参数传递给EnumWindows函数。 平台调用会自动将委托转换为熟悉的回调格式。

  4. 确保垃圾回收器不会在回调函数完成工作之前回收委托。 当您将委托作为参数传递,或将包含在结构中的委托作为字段传递时,该委托在调用期间不被回收。 因此,与以下枚举示例一样,回调函数在调用返回之前完成其工作,并且不需要托管的调用方执行其他操作。

    但是,如果在调用返回后可以调用回调函数,则托管调用方必须采取措施,以确保委托在回调函数完成之前保持未收集状态。 有关示例,请参阅 GCHandle 示例

Example

Imports System
Imports System.Runtime.InteropServices

Public Delegate Function CallBack( _
hwnd As Integer, lParam As Integer) As Boolean

Public Class EnumReportApp

    Declare Function EnumWindows Lib "user32" ( _
       x As CallBack, y As Integer) As Integer

    Public Shared Sub Main()
        EnumWindows(AddressOf EnumReportApp.Report, 0)
    End Sub 'Main

    Public Shared Function Report(hwnd As Integer, lParam As Integer) _
    As Boolean
        Console.Write("Window handle is ")
        Console.WriteLine(hwnd)
        Return True
    End Function 'Report
End Class 'EnumReportApp
using System;
using System.Runtime.InteropServices;

public delegate bool CallBack(int hwnd, int lParam);

public class EnumReportApp
{
    [DllImport("user32")]
    public static extern int EnumWindows(CallBack x, int y);

    public static void Main()
    {
        CallBack myCallBack = new CallBack(EnumReportApp.Report);
        EnumWindows(myCallBack, 0);
    }

    public static bool Report(int hwnd, int lParam)
    {
        Console.Write("Window handle is ");
        Console.WriteLine(hwnd);
        return true;
    }
}
using namespace System;
using namespace System::Runtime::InteropServices;

// A delegate type.
delegate bool CallBack(int hwnd, int lParam);

// Managed type with the method to call.
ref class EnumReport
{
// Report the window handle.
public:
    [DllImport("user32")]
    static int EnumWindows(CallBack^ x, int y);

    static void Main()
    {
        EnumReport^ er = gcnew EnumReport;
        CallBack^ myCallBack = gcnew CallBack(&EnumReport::Report);
        EnumWindows(myCallBack, 0);
    }

    static bool Report(int hwnd, int lParam)
    {
       Console::Write(L"Window handle is ");
       Console::WriteLine(hwnd);
       return true;
    }
};

int main()
{
    EnumReport::Main();
}

另请参阅