方法 : コールバック関数を実装する
更新 : 2007 年 11 月
マネージ アプリケーションが、プラットフォーム呼び出しを使用してローカル コンピュータ上の各ウィンドウのハンドル値を出力する方法の手順と例を次に示します。具体的には、この手順と例では EnumWindows 関数を使ってウィンドウのリストを順次参照し、CallBack という名前のマネージ コールバック関数を使ってウィンドウ ハンドルの値を出力しています。
コールバック関数を実装するには
実装作業を進める前に、EnumWindows 関数のシグネチャを確認します。EnumWindows は、次に示すシグネチャを持っています。
BOOL EnumWindows(WNDENUMPROC lpEnumFunc, LPARAM lParam)
この関数がコールバックを必要とすることは、lpEnumFunc 引数を持っていることからもわかります。コールバック関数へのポインタを受け取る引数の名前には、共通して lp (long ポインタ) プリフィックスと Func サフィックスが付けられています。Win32 関数のドキュメントについては、プラットフォーム SDK を参照してください。
マネージ コールバック関数を作成します。この例では、2 つの引数 (hwnd と lparam) を受け取る、CallBack という名前のデリゲート型が宣言されています。第 1 の引数はウィンドウへのハンドルで、第 2 の引数はアプリケーションで定義します。このリリースでは、どちらの引数も整数である必要があります。
一般にコールバック関数は、成功した場合には 0 以外の値を返し、失敗した場合には 0 を返します。この例では、列挙を続行するために、戻り値を明示的に true に設定しています。
デリゲートを作成し、そのオブジェクトを引数として EnumWindows 関数に渡します。デリゲートは、プラットフォーム呼び出しによって自動的に既知のコールバック形式に変換されます。
コールバック関数が動作を完了する前にガベージ コレクタがデリゲートをクリアしないようにする必要があります。デリゲートをパラメータとして渡したり、構造体にフィールドとして格納されているデリゲートを渡したりした場合、そのデリゲートは呼び出しの存続期間を通じて収集されずに残ります。そのため、次に示す列挙型の例のように、コールバック関数は呼び出しが戻される前に動作を完了し、マネージ呼び出し元による追加のアクションは必要としません。
しかし、呼び出しが戻された後でコールバック関数が呼び出される可能性がある場合には、マネージ呼び出し元で、コールバック関数の動作完了まではデリゲートが収集されないようにするために必要な手順を行う必要があります。ガベージ コレクションを避ける方法の詳細については、「相互運用マーシャリング」と、Platform 呼び出しに関するトピックを参照してください。
使用例
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::Runtime::InteropServices;
// A delegate type.
__delegate bool CallBack(int hwnd, int lParam);
// Managed type with the method to call.
__gc class EnumReport
{
// Report the window handle.
public:
bool Report(int hwnd, int lParam) {
Console::Write(L"Window handle is ");
Console::WriteLine(hwnd);
return true;
}
};
[DllImport("user32")]
extern "C" int EnumWindows(CallBack* x, int y);
void main(void) {
EnumReport* er = new EnumReport;
CallBack* myCallBack = new CallBack(er, &EnumReport::Report);
EnumWindows(myCallBack, 0);
}