ウィンドウなしのアクティベーション
更新 : 2007 年 11 月
ウィンドウを作成するコード、つまり CreateWindow の呼び出しに伴うすべての処理の実行には時間がかかります。画面上にウィンドウを保持するコントロールでは、ウィンドウへのメッセージを管理する必要があります。このため、ウィンドウなしのコントロールの方がウィンドウつきのコントロールより実行速度が速くなります。
さらに、ウィンドウなしのコントロールでは、透過的な描画や四角形以外の画面領域がサポートされています。これらは、ウィンドウを持つコントロールではサポートされていません。透過的なコントロールの例としては、透過な背景を持つテキスト コントロールがあります。透過な背景を持つテキスト コントロールでは、描画されるのはテキストだけで、背景は描画されないため、テキストの背景にあるものはすべて透けて見えます。新しいフォームでは、矢印や丸いボタンなどの四角形以外のコントロールがよく使用されています。
コントロールは、多くの場合、固有のウィンドウを必要としません。代わりにコンテナのウィンドウ サービスを利用できます。ただし、コンテナ側でウィンドウなしのオブジェクトがサポートされている必要があります。ウィンドウなしのコントロールは、古いコンテナとの下位互換性があります。これにより、ウィンドウなしのコントロールがサポートされていない古いコンテナ内でアクティブになると、コントロールはウィンドウを作成します。
ウィンドウなしのコントロールには固有のウィンドウがないため、本来コントロール自身のウィンドウによって提供されるはずのサービスが、ウィンドウを持つコンテナによって提供されることになります。たとえば、キーボード フォーカスの問い合わせ、マウスのキャプチャ、デバイス コンテキストの取得などの操作は、コンテナによって管理されます。コンテナは、IOleInPlaceObjectWindowless インターフェイスを使って、コンテナのウィンドウに送られたユーザー入力メッセージを適切なウィンドウなしのコントロールに送ります。このインターフェイスの詳細については、『ActiveX SDK』を参照してください。これらのサービスは、COleControl のメンバ関数によってコンテナから呼び出されます。
コントロールでウィンドウなしのアクティベーションを使用するには、COleControl::GetControlFlags によって返される一連のフラグに windowlessActivate フラグを含めます。次に例を示します。
DWORD CMyAxOptCtrl::GetControlFlags()
{
DWORD dwFlags = COleControl::GetControlFlags();
...
// The control can activate without creating a window.
dwFlags |= windowlessActivate;
...
return dwFlags;
}
このフラグを含めるコードを自動生成するには、MFC ActiveX コントロール ウィザードの [コントロールの設定] ページの [ウィンドウなしでアクティブ] オプションを選択します。
ウィンドウなしのアクティベーションが有効になっていると、コンテナは、入力メッセージをコントロールの IOleInPlaceObjectWindowless インターフェイスに渡します。IOleInPlaceObjectWindowless インターフェイスの COleControl の実装は、マウスの座標を適切に調整した後、コントロールのメッセージ マップを通じてメッセージをディスパッチします。対応するエントリをメッセージ マップに追加すると、メッセージを通常のウィンドウ メッセージと同じように処理できます。メッセージを処理するハンドラで m_hWnd メンバ変数 (またはこのメンバ変数を使用するメンバ関数) を使用する場合は、値が NULL でないことを必ず事前に確認してください。
COleControl には、次のようなメンバ関数があります。これらのメンバ関数は、マウスのキャプチャ、キーボード フォーカス、スクロールなどのウィンドウ サービスを必要に応じてコンテナから呼び出します。
ウィンドウなしのコントロールでは、常に COleControl のメンバ関数を使用します。対応する CWnd のメンバ関数やそれに関連する Win32 API 関数は使用しません。
ウィンドウなしのコントロールを OLE ドラッグ アンド ドロップ操作のターゲットにすることもできます。通常これには、コントロールのウィンドウをドロップ ターゲットとして登録する必要があります。ウィンドウなしのコントロールにはウィンドウがないため、コンテナのウィンドウがドロップ ターゲットとして使用されます。コントロールは IDropTarget インターフェイスの実装を提供し、コンテナが必要に応じてこのインターフェイスを呼び出します。IDropTarget インターフェイスをコンテナに公開するには、COleControl::GetWindowlessDropTarget をオーバーライドします。次に例を示します。
IDropTarget* CMyAxOptCtrl::GetWindowlessDropTarget()
{
m_DropTarget.m_xDropTarget.AddRef();
return &m_DropTarget.m_xDropTarget;
}