HOW TO:實作回呼函式
下列程序和範例示範 Managed 應用程式如何 (使用平台叫用) 列印本機電腦上每個視窗的控制代碼值。 特別的是,程序和範例會使用 EnumWindows 函式逐步執行視窗清單,並使用 Managed 回呼函式 (Callback Function) (名為 CallBack) 列印視窗控制代碼值。
若要實作回呼函式
在繼續進行實作之前,先查看 EnumWindows 函式的簽章。 EnumWindows 具有以下簽章:
BOOL EnumWindows(WNDENUMPROC lpEnumFunc, LPARAM lParam)
有個跡象可以看出這個函式需要回呼函式,就是它有個 lpEnumFunc 引數。 常常可以看到 lp (長指標 (Long Pointer)) 前置詞與 Func 後置詞,組合使用於接受指向回呼函式之指標的引數名稱中。 如需 Win32 函式的文件,請參閱 Microsoft Platform SDK。
建立 Managed 回呼函式。 範例中宣告了一個用來接受兩個引數 (hwnd 和 lparam) 的委派型別 (Delegate Type),名稱為 CallBack。 第一個引數是視窗的控制代碼;第二個引數是應用程式定義的。 在這個版本中,這兩個引數都必須是整數。
回呼函式通常會傳回非零值以表示成功,而零則表示失則。 這個範例是將傳回值明確地設定為 True 以繼續進行列舉。
建立委派物件,並將它當做引數傳遞給 EnumWindows 函式。 平台叫用會自動將這個委派物件轉換為熟悉的回呼格式。
在回呼函式完成工作之前,確定記憶體回收行程不會重新宣告委派。 當您將委派當做參數傳遞,或是傳遞內含在結構中當做欄位的委派時,在呼叫期間不會將它回收。 因此,在下面這個列舉型別的範例中,回呼函式會在呼叫傳回之前先完成它的工作,而且不會要求 Managed 呼叫端採取其他動作。
但是,如果呼叫函式可在呼叫傳回之後再叫用,Managed 呼叫端必須採取一些步驟,以確保在回呼函式完成之前不會將委派回收。 如需避免記憶體回收的詳細資訊,請參閱平台叫用的 Interop 封送處理。
範例
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();
}