Compartilhar via


Como implementar funções de retorno de chamada

O procedimento e o exemplo a seguir demonstram como um aplicativo gerenciado, usando a invocação de plataforma, pode imprimir o valor do identificador para cada janela no computador local. Especificamente, o procedimento e o exemplo usam a função EnumWindows para percorrer a lista de janelas e uma função de retorno de chamada gerenciada (nomeada CallBack) para imprimir o valor do identificador da janela.

Para implementar uma função de retorno de chamada

  1. Examine a assinatura da EnumWindows função antes de ir mais longe com a implementação. EnumWindows tem a seguinte assinatura:

    BOOL EnumWindows(WNDENUMPROC lpEnumFunc, LPARAM lParam)
    

    Uma pista de que essa função requer um callback é a presença do argumento lpEnumFunc. É comum ver o lp prefixo (ponteiro longo) combinado com o Func sufixo no nome dos argumentos que recebem um ponteiro para uma função de callback. Para obter documentação sobre as funções do Win32, consulte o SDK da Plataforma Microsoft.

  2. Crie a função de retorno de chamada gerenciada. O exemplo declara um tipo delegado, chamado CallBack, que usa dois argumentos (hwnd e lparam). O primeiro argumento é um "handle" para a janela; o segundo argumento é definido pelo aplicativo. Nesta versão, ambos os argumentos devem ser inteiros.

    As funções de retorno de chamada geralmente retornam valores não zero para indicar êxito e zero para indicar falha. Este exemplo define explicitamente o valor de retorno como true para continuar a enumeração.

  3. Crie um delegado e passe-o como um argumento para a função EnumWindows. A invocação de plataforma converte o delegado em um formato de retorno de chamada familiar automaticamente.

  4. Verifique se o coletor de lixo não reclama o delegado antes que a função de callback conclua seu trabalho. Quando você passa um delegado como parâmetro, ou passa um delegado contido como campo em uma estrutura, ele permanece sem ser coletado durante toda a duração da chamada. Portanto, como é o caso no exemplo de enumeração a seguir, a função de retorno de chamada conclui seu trabalho antes que a chamada retorne e não requer nenhuma ação adicional do chamador gerenciado.

    Se, no entanto, a função de retorno de chamada puder ser invocada após o retorno da chamada, o chamador gerido deverá tomar medidas para garantir que o delegado não seja coletado até a função de retorno de chamada ser concluída. Para obter um exemplo, consulte o exemplo de 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 também