Instrukcje: implementowanie funkcji wywołania zwrotnego

Poniższa procedura i przykład pokazują, jak zarządzana aplikacja przy użyciu wywołania platformy może wydrukować wartość uchwytu dla każdego okna na komputerze lokalnym. W szczególności procedura i przykład użyj funkcji EnumWindows , aby przejść przez listę okien i zarządzaną funkcję wywołania zwrotnego (o nazwie CallBack), aby wydrukować wartość uchwytu okna.

Aby zaimplementować funkcję wywołania zwrotnego

  1. Przed kontynuowaniem implementacji przyjrzyj się podpisowi funkcji EnumWindows . EnumWindows ma następujący podpis:

    BOOL EnumWindows(WNDENUMPROC lpEnumFunc, LPARAM lParam)
    

    Jedną z wskazówek, że ta funkcja wymaga wywołania zwrotnego, jest obecność argumentu lpEnumFunc . Często można zobaczyć prefiks lp (długi wskaźnik) w połączeniu z sufiksem Func w nazwie argumentów, które przyjmują wskaźnik do funkcji wywołania zwrotnego. Aby uzyskać dokumentację dotyczącą funkcji Win32, zobacz zestaw Microsoft Platform SDK.

  2. Utwórz funkcję zarządzanego wywołania zwrotnego. W przykładzie zadeklarowano typ delegata o nazwie CallBack, który przyjmuje dwa argumenty (hwnd i lparam). Pierwszym argumentem jest uchwyt do okna; drugi argument jest zdefiniowany przez aplikację. W tej wersji oba argumenty muszą być liczbami całkowitymi.

    Funkcje wywołania zwrotnego zwykle zwracają wartości inne niżzerowe, aby wskazać powodzenie i zero, aby wskazać niepowodzenie. W tym przykładzie jawnie ustawia wartość zwracaną na true , aby kontynuować wyliczanie.

  3. Utwórz delegata i przekaż go jako argument do funkcji EnumWindows . Platforma automatycznie konwertuje delegata na znany format wywołania zwrotnego.

  4. Upewnij się, że moduł odśmieceń pamięci nie odzyskuje delegata przed ukończeniem pracy funkcji wywołania zwrotnego. Po przekazaniu delegata jako parametru lub przekazaniu delegata zawartego jako pole w strukturze pozostaje on nieokreślony przez czas trwania wywołania. Tak więc, jak w poniższym przykładzie wyliczenia, funkcja wywołania zwrotnego kończy swoją pracę przed zwróceniem wywołania i nie wymaga dodatkowej akcji zarządzanego wywołującego.

    Jeśli jednak funkcja wywołania zwrotnego może zostać wywołana po powrocie wywołania, zarządzany obiekt wywołujący musi wykonać kroki, aby upewnić się, że delegat pozostanie niezachłoczony do momentu zakończenia funkcji wywołania zwrotnego. Przykład można znaleźć w przykładzie GCHandle.

Przykład

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();  
}  

Zobacz też