[ヘルプ] メニューのマージ

更新 : 2007 年 11 月

コンテナ内のオブジェクトをアクティブにすると、OLE ドキュメントのメニューをマージするプロトコルによって、[ヘルプ] メニューがオブジェクト側で完全に制御されるようになります。このため、ユーザーがオブジェクトを非アクティブにしない限り、コンテナのヘルプ トピックが利用できなくなります。Active ドキュメント コンテインメント アーキテクチャでは、埋め込み先編集用メニューのマージ規則が拡張され、コンテナとアクティブな Active ドキュメントがメニューを共有できるようになりました。新しい規則では、どのコンポーネントがメニューのどの部分を所有するのか、また共有メニューがどのように構築されるかが決定されます。

新しい規約の内容は簡単です。Active ドキュメントでは、[ヘルプ] メニューは次のように 2 つのトップレベル メニュー項目から構成されます。

Help

Container Help >

Object Help >

たとえば、Office バインダーで Word セクションがアクティブな場合は、[ヘルプ]メニューは次のように表示されます。

Help

Binder Help >

Word Help >

任意の追加メニュー項目をコンテナとオブジェクトに指定すると、どちらのメニュー項目もカスケード メニューになります。表示されるメニュー項目は、コンテナとオブジェクトによって異なります。

このマージされた [ヘルプ] メニューを作成するために、Active ドキュメント コンテインメント アーキテクチャは、標準の OLE ドキュメント プロシージャを変更します。OLE ドキュメントでは、マージされたメニュー バーには、[ファイル]、[編集]、[コンテナ]、[Object]、[ウィンドウ]、[ヘルプ] の順に 6 つのメニュー グループが作成されます。各グループには、複数のメニューがある場合も、まったくない場合もあります。[ファイル]、[コンテナ]、 [ウィンドウ] はコンテナに属し、[編集]、[オブジェクト]、[ヘルプ] はオブジェクトに属します。オブジェクトがメニューをマージすると、空白のメニュー バーが作成されて、コンテナに渡されます。コンテナは、IOleInPlaceFrame::InsertMenus を呼び出して、コンテナのメニューを挿入します。オブジェクトは、6 つの LONG 値型配列 (OLEMENUGROUPWIDTHS) 構造体も渡します。メニューを挿入した後、コンテナは各グループに追加したメニューの数をこの配列で返します。次に、オブジェクトは各コンテナ グループに追加されたメニュー数を考慮し、オブジェクト側のメニューを挿入します。最後に、オブジェクトはマージされたメニュー バーと、各グループのメニュー数を格納した配列を OLE に渡します。OLE は非透過な "メニュー記述子" ハンドルをオブジェクトに返します。オブジェクトは IOleInPlaceFrame::SetMenu を呼び出して、このハンドルとマージ後のメニュー バーをコンテナに渡します。コンテナはマージされたメニュー バーを表示し、ハンドルを OLE に渡します。これで、OLE がメニュー メッセージを適切にディスパッチできるようになります。

変更された Active ドキュメント プロシージャでは、オブジェクトはコンテナに渡す前に、OLEMENUGROUPWIDTHS の全要素を 0 に初期化する必要があります。次に、コンテナは通常の手順どおりにメニューを挿入します。ただしその前に、[ヘルプ] メニューを最後の項目として挿入し、OLEMENUGROUPWIDTHS 配列の最後 (6 番目) のエントリ width[5] (オブジェクトの [ヘルプ] グループ) に値 1 を格納します。この [ヘルプ] メニューには、サブメニューとして項目が 1 つだけあります。それは、前述の "[コンテナのヘルプ]" というカスケード メニューです。

次に、オブジェクトは、通常のメニュー挿入コードどおりに処理を実行します。ただし、[ヘルプ] メニューを挿入する前に、OLEMENUGROUPWIDTHS 配列の 6 番目のエントリを調べます。この値が 1 で、最後のメニュー名が "ヘルプ" の場合、オブジェクトはコンテナの [ヘルプ] メニューのサブメニューとして自分の [ヘルプ] メニューを挿入します。

次に、オブジェクトは OLEMENUGROUPWIDTHS の 6 番目の要素を 0 に設定し、5 番目の要素の値を 1 増分します。これにより、OLE はこの [ヘルプ] メニューがコンテナに属しており、このメニューとサブメニューからのメニュー メッセージの送り先はコンテナであると判断できるようになります。この結果、オブジェクトの [ヘルプ] メニューからの WM_INITMENUPOPUPWM_SELECTWM_COMMAND などのメニュー関連メッセージは、コンテナによって転送されます。この処理は、ユーザーのポイントした位置がオブジェクトの [ヘルプ] メニューかどうかを示すフラグが、WM_INITMENU によってクリアされると実行されます。コンテナは、コンテナ側で追加しなかった [ヘルプ] メニュー項目へのポインタの出入りを WM_MENUSELECT で調べます。ポインタの進入時、つまりユーザーがオブジェクト側メニューをポイントすると、コンテナは "オブジェクト側 [ヘルプ] メニュー" フラグをオンにします。このフラグがセットされると、WM_MENUSELECTWM_INITMENUPOPUPWM_COMMAND メッセージなどがオブジェクト ウィンドウに転送されます。ポインタがオブジェクト メニューから離れると、コンテナはフラグをクリアし、メッセージをコンテナ側で処理します。コンテナは、これらのメッセージの送り先として、オブジェクトの IOleInPlaceActiveObejct::GetWindow 関数から返されたウィンドウを使用します。

OLEMENUGROUPWIDTHS の 6 番目の要素値が 0 の場合、オブジェクトは OLE ドキュメントの通常の規則に従ってメニューを処理します。つまり、[ヘルプ] メニューをマージするコンテナもしないコンテナも処理されます。

マージされたメニュー バーを表示する前にオブジェクトが IOleInPlaceFrame::SetMenu を呼び出した場合、コンテナは、コンテナ側で追加したサブメニュー以外のサブメニューが [ヘルプ] メニューにあるかどうかを調べます。ある場合は、コンテナはその [ヘルプ] メニューをマージされたメニュー バーにそのまま残します。[ヘルプ] メニューにほかのサブメニューがない場合は、その[ヘルプ] メニューをマージされたメニュー バーから削除します。これにより、[ヘルプ] メニューをマージするオブジェクトもマージしないオブジェクトも処理されます。

メニューの逆アセンブリ時、オブジェクトは [ヘルプ] メニューなどのオブジェクト側で追加したすべてのメニューを削除します。コンテナが自分のメニューを削除する場合も、[ヘルプ] メニューなどのコンテナ側で追加したすべてのメニューを削除します。

参照

概念

Active ドキュメント コンテナ