Gewusst wie: Implementieren von Rückruffunktionen
Der folgende Prozess veranschaulicht zusammen mit dem folgenden Beispiel, wie eine verwaltete Anwendung mithilfe von Plattformaufruf den Handlewert eines jeden Fensters auf dem lokalen Computer drucken kann. Im Prozess und im Beispiel wird mit der EnumWindows-Funktion die Liste der Fenster schrittweise durchlaufen und mit einer verwalteten Rückruffunktion (genannt CallBack) der Wert des Fensterhandles gedruckt.
So implementieren Sie eine Rückruffunktion
Prüfen Sie die Signatur der EnumWindows-Funktion, bevor Sie mit der Implementierung fortfahren. EnumWindows hat folgende Signatur:
BOOL EnumWindows(WNDENUMPROC lpEnumFunc, LPARAM lParam)
Einen Hinweis darauf, dass für diese Funktion ein Rückruf erforderlich ist, stellt das lpEnumFunc-Argument dar. Die Kombination des lp (long pointer)-Präfix mit dem Func-Suffix im Namen eines Arguments weist oft auf einen Zeiger für eine Rückruffunktion hin. Die Dokumentation zu Win32-Funktionen finden Sie in Microsoft Platform SDK.
Erstellen Sie die verwaltete Rückruffunktion. Im Beispiel wird ein Delegattyp namens CallBack mit zwei Argumenten (hwnd und lparam) deklariert. Das erste Argument ist ein Handle für das Fenster, das zweite wird von der Anwendung definiert. In dieser Version müssen beide Argumente ganze Zahlen sein.
Rückruffunktionen geben i. d. R. bei Erfolg Werte zurück, die nicht 0 sind, bei Misserfolg wird 0 zurückgegeben. In diesem Beispiel wird der zurückgegebene Wert explizit auf true festgelegt, um mit der Enumeration fortzufahren.
Erstellen Sie einen Delegaten, und übergeben Sie diesen als Argument an die EnumWindows-Funktion. Der Delegat wird durch Plattformaufruf automatisch in ein bekanntes Rückrufformat konvertiert.
Stellen Sie sicher, dass der Garbage Collector den Delegaten nicht vor Abschluss der Rückruffunktion freigibt. Wenn Sie einen Delegaten als Parameter oder einen als Feld in einer Struktur enthaltenen Delegaten übergeben, wird für diesen während der Dauer des Aufrufs keine Garbage Collection durchgeführt. Wie im folgenden Enumerationsbeispiel zu sehen, wird die Rückruffunktion abgeschlossen, bevor der Aufruf zurückgegeben wird, und erfordert keine zusätzliche Aktion des verwalteten Aufrufers.
Wenn die Rückruffunktion hingegen aufgerufen werden kann, nachdem der Aufruf zurückgegeben wurde, muss der verwaltete Aufrufer sicherstellen, dass für den Delegaten bis zum Abschluss der Rückruffunktion keine Garbage Collection durchgeführt wird. Detaillierte Informationen dazu, wie Sie die Garbage Collection verhindern können, finden Sie unter Interop-Marshalling mit Plattformaufruf.
Beispiel
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();
}