テクニカル ノート 3: Windows ハンドルとオブジェクト間のマップ

ここでは、C++ オブジェクトへの Windows オブジェクト ハンドルのマッピングをサポートする MFC ルーチンについて説明します。

問題

通常、Windows オブジェクトはさまざまな HANDLE オブジェクトによって表されます。MFC クラスは、C++ オブジェクトで Windows オブジェクト ハンドルをラップします。 MFC クラス ライブラリのハンドル ラップ関数を使用して、特定のハンドルを持つ Windows オブジェクトをラップしている C++ オブジェクトを検索できます。 ただし、オブジェクトに C++ ラッパー オブジェクトが存在しない場合があります。このような場合、システムは C++ ラッパーとして機能する一時オブジェクトを作成します。

ハンドル マップを使用する Windows オブジェクトの一覧は次のとおりです。

  • HWND (CWnd および CWnd 派生クラス)

  • HDC (CDC および CDC 派生クラス)

  • HMENU (CMenu)

  • HPEN (CGdiObject)

  • HBRUSH (CGdiObject)

  • HFONT (CGdiObject)

  • HBITMAP (CGdiObject)

  • HPALETTE (CGdiObject)

  • HRGN (CGdiObject)

  • HIMAGELIST (CImageList)

  • SOCKET (CSocket)

これらのオブジェクトにハンドルを指定すると、静的メソッド FromHandle を呼び出すことによって、ハンドルをラップする MFC オブジェクトを検索できます。 たとえば、hWnd という HWND を指定すると、次の行は hWnd をラップする CWnd へのポインターを返します。

CWnd::FromHandle(hWnd)

hWnd に特定のラッパー オブジェクトが存在しない場合、一時的な CWnd が作成されて hWnd がラップされます。 これにより、任意のハンドルから有効な C++ オブジェクトを取得できます。

ラッパー オブジェクトを作成した後は、ラッパー クラスのパブリック メンバー変数からそのハンドルを取得できます。 CWnd の場合、m_hWnd にはそのオブジェクトの HWND が含まれます。

MFC オブジェクトへのハンドルのアタッチ

新しく作成されたハンドル ラッパー オブジェクトと Windows オブジェクトへのハンドルを指定すると、次の例のように Attach 関数を呼び出すことによって、2 つを関連付けることができます。

CWnd myWnd;
myWnd.Attach(hWnd);

これにより、myWndhWnd を関連付ける永続的なマップにエントリが作成されます。 CWnd::FromHandle(hWnd) を呼び出すと、myWnd へのポインターが返されるようになります。 myWnd が削除されると、デストラクターはWindows DestroyWindow 関数を呼び出して hWnd を自動的に破棄します。 これを行いたくない場合は、myWnd が破棄される前に hWndmyWnd からデタッチする必要があります (通常は、myWnd が定義されたスコープを離れるとき)。 Detach メソッドによってこれが行われます。

myWnd.Detach();

一時オブジェクトの詳細

一時オブジェクトは、ラッパー オブジェクトをまだ持っていないハンドルが FromHandle に指定されるたびに作成されます。 これらの一時オブジェクトはハンドルからデタッチされ、DeleteTempMap 関数によって削除されます。 既定では、CWinThread::OnIdle は、一時ハンドル マップをサポートするクラスごとに自動的に DeleteTempMap を呼び出します。 つまり、一時オブジェクトへのポインターが、ポインターが取得された関数の終了時点を過ぎた時点から有効になるとは想定できません。

ラッパー オブジェクトと複数のスレッド

一時オブジェクトと永続的オブジェクトは、どちらもスレッドごとに保持されます。 つまり、あるスレッドは、一時的か永続的かにかかわらず、別のスレッドの C++ ラッパー オブジェクトにアクセスできません。

これらのオブジェクトをスレッド間で渡す場合は、常にネイティブ HANDLE 型として送信します。 C++ ラッパー オブジェクトを 1 つのスレッドから別のスレッドに渡す場合、予期しない結果が生じる可能性があります。

関連項目

番号順テクニカル ノート
カテゴリ別テクニカル ノート