Partilhar via


Como implementar funções de callback

O procedimento e exemplo seguintes demonstram como uma aplicação gerida, usando platform invoke, pode imprimir o valor do handle para cada janela no computador local. Especificamente, o procedimento e o exemplo usam a EnumWindows função para percorrer a lista de janelas e uma função de callback gerida (chamada CallBack) para imprimir o valor do handle da janela.

Para implementar uma função de callback

  1. Veja a assinatura da EnumWindows função antes de avançar com a implementação. EnumWindows tem a seguinte assinatura:

    BOOL EnumWindows(WNDENUMPROC lpEnumFunc, LPARAM lParam)
    

    Uma pista de que esta função requer um callback é a presença do lpEnumFunc argumento. É comum ver o prefixo lp (ponteiro longo) combinado com o sufixo Func nos nomes de argumentos que recebem um ponteiro para uma função de callback. Para documentação sobre funções Win32, consulte o Microsoft Platform SDK.

  2. Crie a função de callback gerida. O exemplo declara um tipo de delegado, chamado CallBack, que toma dois argumentos (hwnd e lparam). O primeiro argumento é uma maçaneta para a janela; O segundo argumento é definido pela aplicação. Nesta versão, ambos os argumentos devem ser inteiros.

    As funções de callback geralmente retornam valores não nulos para indicar sucesso e zero para indicar falha. Este exemplo define explicitamente o valor de retorno como true para prosseguir com a enumeração.

  3. Crie um delegate e passe-o como argumento para a função EnumWindows. O Platform Invoke converte automaticamente o delegado para um formato de callback familiar.

  4. Certifique-se de que o coletor de lixo não reivindica o delegado antes que a função de callback conclua o seu trabalho. Quando passa um delegado como parâmetro, ou passa um delegado contido como campo numa estrutura, ele não é coletado durante toda a chamada. Assim, como acontece no exemplo de enumeração seguinte, a função de callback completa o seu trabalho antes do retorno da chamada e não requer qualquer ação adicional por parte do chamador gerido.

    Se, no entanto, a função de retorno puder ser invocada após o retorno da chamada, o cliente gerido deve tomar medidas para garantir que o delegado não seja liberado até que a função de retorno termine. Para 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