Compartir vía


Cómo implementar funciones de devolución de llamada

En el siguiente procedimiento y ejemplo se muestra cómo una aplicación administrada, mediante la invocación de plataforma, puede imprimir el valor de identificador para cada ventana del equipo local. En concreto, el procedimiento y el ejemplo usan la EnumWindows función para recorrer la lista de ventanas y una función de devolución de llamada administrada (denominada CallBack) para imprimir el valor del identificador de ventana.

Para implementar una función de devolución de llamada

  1. Examine la firma de la EnumWindows función antes de continuar con la implementación. EnumWindows tiene la firma siguiente:

    BOOL EnumWindows(WNDENUMPROC lpEnumFunc, LPARAM lParam)
    

    Una pista de que esta función requiere una devolución de llamada es la presencia del argumento lpEnumFunc. Es habitual ver el prefijo lp (puntero largo) combinado con el sufijo Func en el nombre de los argumentos que toman un puntero a una función callback. Para obtener documentación sobre las funciones de Win32, consulte Microsoft Platform SDK.

  2. Cree la función de devolución de llamada administrada. En el ejemplo se declara un tipo delegado, denominado CallBack, que toma dos argumentos (hwnd y lparam). El primer argumento es un controlador para la ventana; el segundo argumento está definido por la aplicación. En esta versión, ambos argumentos deben ser enteros.

    Las funciones de devolución de llamada generalmente devuelven valores distintos de cero para indicar éxito y cero para indicar un fallo. En este ejemplo se establece explícitamente el valor devuelto en true para continuar con la enumeración.

  3. Cree un delegado y páselo como argumento a la EnumWindows función. La invocación de plataforma convierte el delegado en un formato de devolución de llamada conocido automáticamente.

  4. Asegúrese de que el recolector de basura no libere el delegado antes de que el callback complete su trabajo. Cuando se pasa un delegado como parámetro o se pasa un delegado contenido como un campo en una estructura, permanece no recolectado durante toda la duración de la llamada. Por lo tanto, como sucede en el ejemplo de enumeración siguiente, la función de devolución de llamada completa su trabajo antes de que la llamada regrese y no requiere ninguna acción adicional por parte del cliente administrado.

    Sin embargo, si la función de devolución de llamada se puede invocar después de que se devuelva la llamada, el llamador administrado debe tomar medidas para asegurarse de que el delegado permanezca sin recoger hasta que finalice la función de devolución de llamada. Para obtener un ejemplo, consulte el ejemplo 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();
}

Consulte también