COM
ATLコントロールのHWNDを取得するには?
(2009. 7. 19)
ATLでDirectXの画面を表示させるのには、どうしてもHWNDが必要になるはずです。これについてどこかに情報が無いかと探したのですが、いやぁ〜〜無い・・・。でもかなり古いのですがMicrosoftがサンプルを提供していました。これを参考にATLのウィンドウハンドルを取得してみます。
○ サンプル
元のサンプルはこちら: DIRECT3D C++ Sample
2002年のサンプルでして、このままではもう動きません(Direct3Dのヘッダーが古い)。でも、ウィンドウハンドルを取得する手順がわかりました。
○ ATLコントロールのHWNDを得る
ATLコントロールをプロジェクトに追加している状態からはじめます。ATLコントロールがアクティブになった時、CComControlBase::InPlaceActivateというメソッドが呼ばれるようです。ATLコントロールは通常このインターフェイスを継承しているようなので、自分のATLコントロールのヘッダー部に次のように書く事ができます:
HRESULT InPlaceActivate(LONG iVerb, const RECT* prcPosRect = NULL)
{
return CComControlBase::InPlaceActivate(iVerb, prcPosRect);
}
親の同じメソッドを呼んでおきます。ここでウィンドウハンドルを取得すると良さそうです。ウィンドウハンドルを取得している部分をサンプルから抜粋します:
if (m_bWndLess)
{
HDC hDC;
m_spInPlaceSite->GetDC(NULL, OLEDC_NODRAW, &hDC);
m_hOurWnd = WindowFromDC(hDC);
RECT rect;
::GetClientRect(m_hOurWnd,&rect);
HRGN hRegion = CreateRectRgn(rect.left,rect.top,rect.right,rect.bottom);
SelectClipRgn(hDC,hRegion);
m_spInPlaceSite->ReleaseDC(hDC);
}
else
m_hOurWnd = m_hWnd;
m_bWndLessがtrueの時、これはATLコントロールがウィンドウを持たない状態のようです。この場合自分が置かれているサイトのデバイスコンテキストを取得し、そこからウィンドウハンドルを得ます。ATLコントロールがウィンドウハンドルを持つ場合はm_hWndにすでにウィンドウハンドルが格納されているようです。
この一文をInPlaceActivateメソッド内で呼ぶ事で、自分のATL(もしくは所属している親ウィンドウ)のハンドルを得る事ができます。
○ Web上とVB上と
自分のATLをWeb上(IE)とVB上に置いて、どのウィンドウハンドルが取得されるかテストしてみました。結果、Web上の場合は自身のウィンドウハンドルを持たないようで親のウィンドウハンドルが取得されていました。一方VBは自分のウィンドウを持っていました。それぞれの表示結果はこちら:
左がIE、右がVBです。数字はウィンドウの幅高です。
とりあえずウィンドウハンドルが内部で取得できればDirect3Dの描画デバイスを生成できる・・・はずです。次回はそれにチャレンジ。