テクニカル ノート 71: MFC IOleCommandTarget の実装
更新 : 2007 年 11 月
メモ : |
---|
次のテクニカル ノートは、最初にオンライン ドキュメントの一部とされてから更新されていません。結果として、一部のプロシージャおよびトピックが最新でないか、不正になります。最新の情報について、オンライン ドキュメントのキーワードで関係のあるトピックを検索することをお勧めします。 |
オブジェクトとそのコンテナは、IOleCommandTarget インターフェイスを通じてコマンドをディスパッチします。たとえば、[印刷]、[印刷プレビュー]、[上書き保存]、[新規作成]、[ズーム] などのボタンをツール バーに配置したオブジェクトがあるとします。このオブジェクトの埋め込み先コンテナで IOleCommandTarget がサポートされる場合は、オブジェクトのツール バー ボタンが有効になり、ボタンがクリックされるとコマンドがコンテナに送られます。埋め込み先オブジェクト自身が印刷コマンドを処理する場合は、埋め込みオブジェクトの IOleCommandTarget インターフェイスを通じて、コンテナから印刷を要求するコマンドが送られます。
クライアントがサーバー上のメソッドを呼び出すときに使用するという点で、IOleCommandTarget インターフェイスは、オートメーション インターフェイスに似ています。ただし、IOleCommandTarget では、プログラマが IDispatch の Invoke メソッドを使用する必要がないため、オートメーション インターフェイス経由の呼び出しに伴うオーバーヘッドがありません。通常、このメソッドは大量のリソースを必要とします。
MFC (Microsoft Foundation Class) では、Active ドキュメント サーバー側で IOleCommandTarget インターフェイスを使用して、Active ドキュメント コンテナからのコマンドを受け取ります。Active ドキュメント サーバー クラス CDocObjectServerItem では、MFC インターフェイス マップを使用して、IOleCommandTarget インターフェイスを実装します。詳細については、「テクニカル ノート 38: MFC/OLE IUnknown の実装」を参照してください。
IOleCommandTarget は COleFrameHook クラスでも実装されています。COleFrameHook は、埋め込み先編集コンテナのフレーム ウィンドウ機能を実装する非公開 MFC クラスです。COleFrameHook でも、MFC インターフェイス マップを使用して IOleCommandTarget インターフェイスを実装します。COleFrameHook の IOleCommandTarget は COleDocObjectItem から派生した Active ドキュメント コンテナに OLE コマンドを転送します。このインターフェイスを通じて、どの MFC Active ドキュメント コンテナでも、包含している Active ドキュメント サーバーからのメッセージを受け取ることができます。
MFC OLE コマンド マップ
MFC 開発者は、MFC OLE コマンド マップを使用して IOleCommandTarget を利用できます。OLE コマンドでは、メッセージ マップと同じように、OLE コマンドをコマンド マップの所属先クラスのメンバ関数にマップできます。実際にはコマンド マップに、処理するコマンドの OLE コマンド グループ、OLE コマンド、および OLE コマンドの受信時に送る WM_COMMAND メッセージのコマンド ID を指定するマクロを記述します。MFC には、標準 OLE コマンド用の定義済みマクロが多数用意されています。Microsoft Office アプリケーション用にデザインされた標準 OLE コマンドの一覧については、docobj.h で定義されている OLECMDID 列挙定数を参照してください。
OLE コマンド マップを持つ MFC アプリケーションが OLE コマンドを受け取ると、このコマンドのコマンド ID とコマンド グループが OLE コマンド マップで検索されます。一致するコマンド ID とコマンド グループが見つかると、WM_COMMAND メッセージが、要求されたコマンドの ID によってコマンド マップの所属先アプリケーションにディスパッチされます。以下の ON_OLECMD の説明を参照してください。このように、アプリケーションにディスパッチされた OLE コマンドは、MFC によって WM_COMMAND メッセージに変換されます。この WM_COMMAND メッセージは、MFC の標準コマンド ルーティング アーキテクチャに基づき、アプリケーションのメッセージ マップを通じて転送されます。
メッセージ マップとは異なり、MFC OLE コマンド マップは ClassWizard でサポートされていません。MFC 開発者は、OLE コマンド マップのサポートと OLE コマンド マップ エントリを手作業で追加する必要があります。OLE コマンド マップは、Active ドキュメントがコンテナ内の埋め込み先編集が有効な状態にあるときに、MFC Active ドキュメント サーバーの WM_COMMAND メッセージ ルーティング チェインにある任意のクラスに追加できます。このようなクラスとしては、アプリケーションの CWinApp、CView、CDocument、および COleIPFrameWnd 派生クラスがあります。Active ドキュメント コンテナで OLE コマンド マップを追加できるのは、COleDocObjectItem 派生クラスだけです。また、Active ドキュメント コンテナでは、WM_COMMAND メッセージが COleDocObjectItem 派生クラスのメッセージ マップだけにディスパッチされます。
OLE コマンド マップ マクロ
以下のマクロを使用して、コマンド マップ機能をクラスに追加します。
DECLARE_OLECMD_MAP ()
このマクロは、コマンド マップの所属先クラスのクラス宣言 (通常はヘッダー ファイル) に入れます。
BEGIN_OLECMD_MAP(theClass, baseClass)
theClass
コマンド マップの所属先クラスの名前。baseClass
コマンド マップの所属先クラスの基本クラスの名前。
コマンド マップの開始位置を示します。このマクロは、コマンド マップの所属先クラスの実装ファイルで使用します。
END_OLECMD_MAP()
コマンド マップの終了位置を示します。このマクロは、コマンド マップの所属先クラスの実装ファイルで使用します。このマクロは必ず BEGIN_OLECMD_MAP マクロの後に置きます。
ON_OLECMD(pguid, olecmdid, id)
pguid
OLE コマンドのコマンド グループのグローバル一意識別子 (GUID: Globally Unique Identifier) へのポインタ。標準 OLE コマンド グループの場合は、このパラメータを NULL にします。olecmdid
呼び出されるコマンドの OLE コマンド ID。id
この OLE コマンドが呼び出されたときにコマンド マップの所属先アプリケーションに送る WM_COMMAND メッセージの ID。
コマンド マップで ON_OLECMD マクロを使用して、処理する OLE コマンドのエントリを追加します。アプリケーションに送られた OLE コマンドは、指定された WM_COMMAND メッセージに変換され、標準の MFC コマンド ルーティング アーキテクチャに基づき、アプリケーションのメッセージ マップを通じて転送されます。
使用例
次のコードは、OLE コマンド OLECMDID_PRINT を処理する OLE コマンド処理機能を MFC Active ドキュメント サーバーに追加する例です。この例では、Active ドキュメント サーバー側 MFC アプリケーションが AppWizard で生成されています。
CView 派生クラスのヘッダー ファイルで、DECLARE_OLECMD_MAP マクロをクラス宣言に追加します。
メモ : Active ドキュメント サーバーの WM_COMMAND メッセージ ルーティング チェイン上にあるクラスとして、CView 派生クラスを使用します。
class CMyServerView : public CView { protected: // create from serialization only CMyServerView(); DECLARE_DYNCREATE(CMyServerView) DECLARE_OLECMD_MAP() . . . };
CView 派生クラスの実装ファイルに BEGIN_OLECMD_MAP マクロと END_OLECMD_MAP マクロを追加します。
BEGIN_OLECMD_MAP(CMyServerView, CView) END_OLECMD_MAP()
OLE の標準印刷コマンドを処理するには、ON_OLECMD マクロをコマンド マップに追加して、標準印刷コマンドの OLE コマンド ID と WM_COMMAND ID の ID_FILE_PRINT を指定します。ID_FILE_PRINT は、AppWizard で生成した MFC アプリケーションが使用する標準印刷コマンド ID です。
BEGIN_OLECMD_MAP(CMyServerView, CView) ON_OLECMD(NULL,OLECMDID_PRINT,ID_FILE_PRINT) END_OLECMD_MAP()
ON_OLECMD マクロの代わりに、afxdocob.h で定義されている標準 OLE コマンド マクロも使用できます。これは、OLECMDID_PRINT が OLE の標準コマンド ID であるためです。ON_OLECMD_PRINT マクロの機能は、上の ON_OLECMD マクロと同じです。
コンテナ アプリケーションがこのサーバーに対して、サーバーの IOleCommandTarget インターフェイス経由で OLECMDID_PRINT コマンドを送ると、サーバーの MFC 印刷コマンド ハンドラが呼び出され、アプリケーションを印刷します。上の手順で追加した印刷コマンドを呼び出す Active ドキュメント コンテナのコードは、次のようになります。
void CContainerCntrItem::DoOleCmd()
{
IOleCommandTarget *pCmd = NULL;
HRESULT hr = E_FAIL;
OLECMD ocm={OLECMDID_PRINT, 0};
hr = m_lpObject->QueryInterface(IID_IOleCommandTarget,reinterpret_cast<void**>(&pCmd));
if(FAILED(hr))
return;
hr = pCmd->QueryStatus(NULL, 1, &ocm, NULL);
if(SUCCEEDED(hr) && (ocm.cmdf & OLECMDF_ENABLED))
{
//Command is available and enabled so call it
COleVariant vIn;
COleVariant vOut;
hr = pCmd->Exec(NULL, OLECMDID_PRINT,
OLECMDEXECOPT_DODEFAULT, &vIn, &vOut);
ASSERT(SUCCEEDED(hr));
}
pCmd->Release();
}