Condividi tramite


Procedura: Implementare funzioni di callback

La procedura e l'esempio seguenti illustrano come un'applicazione gestita, usando platform invoke, possa stampare il valore di handle per ogni finestra nel computer locale. In particolare, la routine e l'esempio usano la EnumWindows funzione per scorrere l'elenco di finestre e una funzione di callback gestita (denominata CallBack) per stampare il valore dell'handle di finestra.

Per implementare una funzione di callback

  1. Esaminare la firma per la EnumWindows funzione prima di procedere con l'implementazione. EnumWindows ha la firma seguente:

    BOOL EnumWindows(WNDENUMPROC lpEnumFunc, LPARAM lParam)
    

    Un indizio che questa funzione richiede un callback è la presenza dell'argomento lpEnumFunc . È comune vedere il prefisso lp (puntatore lungo) combinato con il suffisso Func nel nome degli argomenti che accettano un puntatore a una funzione di callback. Per la documentazione sulle funzioni Win32, vedere Microsoft Platform SDK.

  2. Creare la funzione di callback gestita. L'esempio dichiara un tipo delegato, denominato CallBack, che accetta due argomenti (hwnd e lparam). Il primo argomento è un handle per la finestra; il secondo argomento è definito dall'applicazione. In questa versione, entrambi gli argomenti devono essere numeri interi.

    Le funzioni di callback restituiscono in genere valori diversi da zero per indicare l'esito positivo e zero per indicare l'errore. In questo esempio viene impostato in modo esplicito il valore restituito su true per continuare l'enumerazione .

  3. Creare un delegato e passarlo come argomento alla funzione EnumWindows. Platform invoke converte automaticamente il delegato in un formato di callback familiare.

  4. Assicurarsi che il Garbage Collector non recuperi il delegato prima che la funzione di callback completi il proprio lavoro. Quando si passa un delegato come parametro o si passa un delegato contenuto come campo in una struttura, rimane non raccolto per la durata della chiamata. Pertanto, come avviene nell'esempio di enumerazione seguente, la funzione di callback completa il proprio lavoro prima che la chiamata restituisca e non richieda alcuna azione aggiuntiva da parte del chiamante gestito.

    Se, tuttavia, la funzione di callback può essere richiamata dopo la conclusione della chiamata, il chiamante gestito deve eseguire i passaggi per assicurarsi che il delegato resti non raccolto fino al termine della funzione di callback. Per un esempio, vedere l'esempio 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();
}

Vedere anche