Postupy: Implementace funkcí zpětného volání

Následující postup a příklad ukazují, jak spravovaná aplikace pomocí vyvolání platformy může vytisknout hodnotu popisovače pro každé okno v místním počítači. Konkrétně postup a příklad používají funkci EnumWindows k procházení seznamu oken a spravované funkce zpětného volání (pojmenované CallBack) k vytištění hodnoty popisovače okna.

Implementace funkce zpětného volání

  1. Než budete pokračovat v implementaci, podívejte se na podpis funkce EnumWindows . EnumWindows má následující podpis:

    BOOL EnumWindows(WNDENUMPROC lpEnumFunc, LPARAM lParam)
    

    Jednou z vodítek, že tato funkce vyžaduje zpětné volání, je přítomnost argumentu lpEnumFunc . Je běžné vidět předponu lp (dlouhý ukazatel) v kombinaci s příponou Func v názvu argumentů, které přebírají ukazatel na funkci zpětného volání. Dokumentaci k funkcím Win32 najdete v sadě Microsoft Platform SDK.

  2. Vytvořte spravovanou funkci zpětného volání. Příklad deklaruje typ delegáta, který má CallBackdva argumenty (hwnd a lparam). Prvním argumentem je popisovač okna; druhý argument je definovaný aplikací. V této verzi musí být oba argumenty celé číslo.

    Funkce zpětného volání obecně vracejí nenulové hodnoty, které označují úspěch a nulu označující selhání. Tento příklad explicitně nastaví návratové hodnoty na true , aby pokračoval ve výčtu.

  3. Vytvořte delegáta a předejte ho jako argument funkci EnumWindows . Volání platformy převede delegáta na známý formát zpětného volání automaticky.

  4. Před dokončením funkce zpětného volání se ujistěte, že systém uvolňování paměti neuvolní delegáta. Když delegáta předáte jako parametr nebo předáte delegáta obsaženého jako pole ve struktuře, zůstane po dobu trvání volání beze změny. Stejně jako v následujícím příkladu výčtu funkce zpětného volání dokončí svou práci před vrácením volání a nevyžaduje žádnou další akci spravovaného volajícího.

    Pokud je však možné vyvolat funkci zpětného volání po vrácení volání, musí spravovaný volající provést kroky, aby se zajistilo, že delegát zůstane neobsazený, dokud funkce zpětného volání nedokončí. Příklad najdete v ukázce GCHandle.

Příklad

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

Viz také