TN038: MFC および OLE の IUnknown の実装

OLE 2 の中心に「OLE コンポーネント オブジェクト モデル」、または COM. COM 定義を標準どのように協力オブジェクト互いに通信します。これには、どのような「オブジェクト」、上オブジェクト メソッド ディスパッチを含むようの詳細にはが含まれます。COM にもをすべて COM 互換性クラスが派生する基本クラスを定義します。この基本クラスです。IUnknownインターフェイスは、C++ クラスと呼ばれますが、COM は、1 つの言語に固有ではない ? C、PASCAL、または COM オブジェクトのバイナリ レイアウトをサポートすることができます他の言語で実装することができます。

OLE IUnknownから派生した「インタ フェースとして「すべてのクラスを参照IUnknownを実装を運ぶなど、これは重要な違い、「インタ フェース」以来です。それは単にオブジェクト通信、これらの実装は何の仕様しないプロトコルを定義します。これは、最大の柔軟性を許可するシステムを合理的です。MFC および C++ プログラムの既定の動作を実装するには、MFC の仕事です。

IUnknownの MFC の実装を理解するには、まずインターフェイスを理解する必要があります。IUnknown の簡易版を以下に定義されています。:

 iUnknown をクラスします。{パブリック。特価;仮想 HRESULT QueryInterface(REFIID iid, void** ppvObj) = 0;仮想の ULONG AddRef() = 0;仮想の ULONG Release() = 0;}(&N)

特価;この図の特定呼び出し規約の詳細、 _ _stdcallなどが残っています。(&N)。

AddRefおよびReleaseのメンバー関数は、オブジェクトのメモリ管理を制御します。COM では、参照カウント スキームを使用してオブジェクトを追跡します。オブジェクトが参照されることは C++ では、直接。代わりに、COM オブジェクトは常に、ポインターを通じて参照されます。所有者が完了すると、オブジェクトを解放するそれを使用して、オブジェクトのメンバーのリリース(従来の C++ オブジェクトの実行される演算子の削除] を使用してに反対) 呼び出されます。参照カウント手法によって、単一オブジェクトの複数の参照を管理することができます。AddRefおよびReleaseの実装はオブジェクトの参照カウントを保持 ? その参照カウントがゼロに達するまで、オブジェクトは削除されません。

AddRefおよびReleaseは、実装の観点から非常に簡単です。ここでは、単純な実装:

ULONG CMyObj::AddRef() {特価;返す + + m_dwRef;}ULONG CMyObj::Release() {場合 (-m_dwRef = = 0) {この削除;0 を返します。}m_dwRef を返す;}(&N)

QueryInterfaceのメンバー関数は、もう少し興味深いものです。ご想像のとおり、それが唯一のメンバー関数AddRefおよびReleaseオブジェクトには、非常に興味深いではない-それがIUnknownを提供よりもより多くの事を行うには、そのオブジェクトに知らせることができれば。これはQueryInterfaceに便利です。それは、同じオブジェクトで別の「インターフェイス」を取得することができます。これらのインターフェイスは、通常はIUnknownから派生しているし、新しいメンバー関数を追加することによって機能を追加します。COM インターフェイスは、インターフェイスで宣言されたメンバー変数とすべてのメンバー関数が純粋仮想として宣言されています。たとえば,

iPrintInterface クラス: パブリック IUnknown{パブリック。特価;仮想 void PrintObject() = 0;}(&N)

IUnknownをのみがある場合は、IPrintInterface を取得するには、 IIDは IPrintInterface を使用して:queryinterfaceを呼び出します。IIDは、インターフェイスを一意に識別する 128 ビット番号です。または OLE 定義各インターフェイスのIIDです。パンクIUnknownオブジェクトへのポインターの場合は、それから、IPrintInterface を取得するコードがあります。

IPrintInterface ※ pPrint = NULL;場合 (パンク-gt;QueryInterface(IID_IPrintInterface, (void**) & pPrint) NOERROR = =){pPrint - > PrintObject();pPrint - > Release();//リリース ポインター経由で QueryInterface を取得}

かなり簡単なようだが、IPrintInterface とIUnknownの両方のインターフェイスをサポートするオブジェクトを実装する方法?IPrintInterface 直接IUnknownから派生するためには簡単です-IPrintInterface を実装することにより、 IUnknownは自動的にサポートされます。たとえば:

 cPrintObj クラス: パブリック CPrintInterface{特価;仮想 HRESULT QueryInterface(REFIID iid, void** ppvObj);仮想 ULONG AddRef();仮想 ULONG Release();仮想 void PrintObject();}(&N)

AddRefおよびReleaseの実装まさに上記の実装と同じになります。CPrintObj::QueryInterfaceは次のようになります

HRESULT CPrintObj::QueryInterface(REFIID iid, void FAR* FAR* ppvObj){特価;場合 (iid IID_IUnknown = = | | iid IID_IPrintInterface = =){※ ppvObj = この;AddRef();NOERROR を返す;}ResultFromScode(E_NOINTERFACE) を返す;}(&N)

インターフェイス識別子 (IID) が認識される場合、見ることができます、ポインターをオブジェクトに返される;それ以外の場合は、エラーが発生します。また成功QueryInterfaceAddRef黙示のの結果に注意してください。もちろん、あなたもCEditObj::Printを実装する必要があります。IPrintInterface は、 IUnknownインターフェイスから直接派生したので簡単です。ただし、2 つの異なるインターフェイスをサポートする場合は、両方IUnknown派生次を考慮します

iEditInterface クラス: パブリック IUnkown{パブリック。特価;仮想 void EditObject() = 0;}(&N)

IEditInterface と IPrintInterface、複数の継承は、C++ の使用などの両方をサポートするクラスを実装するには、別の方法がありますの数がこのメモこの機能を実装する入れ子になったクラスの使用に集中します。

cEditPrintObj をクラスします。{パブリック。特価;CEditPrintObj();HRESULT QueryInterface(REFIID iid, void**);ULONG AddRef();ULONG Release();DWORD m_dwRef;CPrintObj クラス: パブリック IPrintInterface{パブリック。CEditPrintObj ※ m_pParent;仮想 HRESULT QueryInterface(REFIID iid, void** ppvObj);仮想 ULONG AddRef();仮想 ULONG Release();} m_printObj;CEditObj クラス: パブリック IEditInterface{パブリック。CEditPrintObj ※ m_pParent;仮想 ULONG QueryInterface(REFIID iid, void** ppvObj);仮想 ULONG AddRef();仮想 ULONG Release();} m_editObj;}(&N)

以下が全体の実装が含まれています:

CEditPrintObj::CEditPrintObj(){特価;m_editObj.m_pParent = この;m_printObj.m_pParent = この;}ULONG CEditPrintObj::AddRef() {返す + + m_dwRef;}CEditPrintObj::Release(){場合 (-m_dwRef = = 0){この削除;0 を返します。}m_dwRef を返す;}HRESULT CEditPrintObj::QueryInterface(REFIID iid, void** ppvObj){場合 (iid IID_IUnknown = = | | iid IID_IPrintInterface = =){※ ppvObj = & m_printObj;AddRef();NOERROR を返す;}他の場合 (iid IID_IEditInterface = =){※ ppvObj = & m_editObj;AddRef();NOERROR を返す;}ResultFromScode(E_NOINTERFACE) を返す;}ULONG CEditPrintObj::CEditObj::AddRef() {m_pParent - 戻る > AddRef();}ULONG CEditPrintObj::CEditObj::Release() {m_pParent - 戻る > Release();}HRESULT CEditPrintObj::CEditObj::QueryInterface (REFIID iid、void 年 ppvObj) {m_pParent - 戻る > QueryInterface (iid、ppvObj);}ULONG CEditPrintObj::CPrintObj::AddRef() {m_pParent - 戻る > AddRef();}ULONG CEditPrintObj::CPrintObj::Release() {m_pParent - 戻る > Release();}HRESULT CEditPrintObj::CPrintObj::QueryInterface (REFIID iid、void 年 ppvObj) {m_pParent - 戻る > QueryInterface (iid、ppvObj);}

IUnknownの実装のほとんどを確認 CEditPrintObj::CEditObj と CEditPrintObj::CPrintObj のコードを複製するのではなく、 CEditPrintObjクラスに配置されます。これは、コードの量を減らすし、バグを回避できます。ここで重要なポイントは、IUnknown インターフェイスからは、オブジェクトがサポートする任意のインターフェイスを取得するには、 QueryInterfaceを呼び出すことです、それぞれこれらのインターフェイスからは、同じように可能です。これは、各インターフェイスから利用可能なすべてのQueryInterface関数とまったく同じ方法を動作する必要があることを意味します。埋め込みオブジェクトから、「外側のオブジェクト」で、実装を呼び出すために、バック ポインター (m_pparent) です。M_pParent ポインターは、CEditPrintObj コンス トラクターで初期化されます。[CEditPrintObj::CPrintObj::PrintObject と CEditPrintObj::CEditObj::EditObject などを実装します。コードのかなりのビットが 1 つの機能を追加する追加された ? オブジェクトを編集する機能。幸いにも、インターフェイスを (それを実現するが) 1 つのメンバー関数だけにかなり共通ではない、このケースでは、EditObject、PrintObject 通常、1 つのインターフェイスに結合されます。

それは多くの説明と、多くのコードのような単純なシナリオです。MFC および OLE クラスは単純な選択肢を提供します。MFC 実装、技術の Windows メッセージをラップするようにメッセージ マップを使用します。この施設のインターフェイス マップと呼ばれ、次のセクションで説明。

MFC インターフェイス マップ

MFC および OLE には MFC の「メッセージ マップ」と「ディスパッチ マップ」に類似の「インターフェイス マップ」の実装の概念と実行が含まれます。MFC のインターフェイス マップのコア機能をとおりです。:

また、インターフェイス マップ次の高度な機能をサポートします。:

集計の詳細については、 OLE プログラマ リファレンスを参照してください。

MFC のインターフェイス マップのサポートは、 CCmdTargetクラスに根ざしています。CCmdTargetが、「(参照カウントたとえばだCCmdTargetIUnknownの実装に関連付けられているすべてのメンバー関数と同様にカウントを参照します。OLE COM をサポートするクラスを作成するには、 CCmdTargetからクラスを派生、さまざまなマクロを使用して、目的のインターフェイスを実装するには、 CCmdTargetのメンバー関数と同様。MFC の実装では、入れ子になったクラスを使用して上記の例と同じように、それぞれのインターフェイス実装を定義します。これは、IUnknown として多数の反復的なコードの一部を排除するマクロの標準の実装を容易になります。

インターフェイス マップの基礎

MFC のインターフェイスを使用して、クラスを実装するには、マップこれら手順を実行します:

  1. 直接または間接のいずれかからクラスを派生CCmdTarget

  2. DECLARE_INTERFACE_MAP関数は、派生クラスの定義で使用します。

  3. 各インターフェイスの希望をサポート、クラス定義で、 BEGIN_INTERFACE_PARTEND_INTERFACE_PARTマクロを使用するには。

  4. 実装ファイルでは、 BEGIN_INTERFACE_MAPEND_INTERFACE_MAPのマクロを使用して、クラスのインターフェイス マップを定義するのには。

  5. サポートされている各 IID のINTERFACE_PARTマクロ、特定のクラスの「部分」IID をマップするには、 BEGIN_INTERFACE_MAPEND_INTERFACE_MAPマクロ間使用。

  6. それぞれがサポートするインターフェイスを表す、入れ子になったクラスの実装します。

  7. METHOD_PROLOGUEマクロを使用して、親は、 CCmdTargetをアクセスする-派生オブジェクト。

  8. AddRefリリース、およびQueryInterfaceこれらの関数 (ExternalAddRefExternalRelease、およびExternalQueryInterface) のCCmdTargetの実装に委任することができます。

上記の CPrintEditObj の例は次のとおり実施される可能性が:

cPrintEditObj クラス: パブリック CCmdTarget{パブリック。特価;・ ・ CPrintEditObj のメンバーのデータとメンバーはここに行く・ インターフェイス マップ保護。DECLARE_INTERFACE_MAP()BEGIN_INTERFACE_PART (EditObj, IEditInterface)STDMETHOD_ (void、EditObject)();END_INTERFACE_PART(EditObj)BEGIN_INTERFACE_PART (PrintObj, IPrintInterface)STDMETHOD_ (void、PrintObject)();END_INTERFACE_PART(PrintObj)}(&N)

上記の宣言は、 CCmdTargetから派生したクラスを作成します。DECLARE_INTERFACE_MAPマクロは、このクラスは、カスタム インターフェイス マップが、フレームワークを指示します。さらに、 BEGIN_INTERFACE_PARTEND_INTERFACE_PARTのマクロ入れ子になったクラスは、この場合名 CEditObj と CPrintObj (X はのみ、入れ子になったクラス"C"を開始グローバル クラスとは」と「まずインターフェイス クラスから区別するために使用されます) を定義します。これらのクラスの 2 つの入れ子になったメンバーが作成されます: m_CEditObj、および m_CPrintObj、それぞれ。マクロは自動的にAddRefリリース、およびQueryInterface関数を宣言する;したがって、のみ関数を特定するにはこのインターフェイス宣言: EditObject、PrintObject ( STDMETHODです、OLE マクロ使用など_stdcallと仮想のキーワード ターゲット プラットフォームに応じて提供されるように)。

このクラスのインターフェイス マップを実装するには:

BEGIN_INTERFACE_MAP (CPrintEditObj、CCmdTarget)特価;INTERFACE_PART (CPrintEditObj、IID_IPrintInterface、PrintObj)INTERFACE_PART (CPrintEditObj、IID_IEditInterface、EditObj)END_INTERFACE_MAP()(&N)

これは、IID_IPrintInterface IID m_CPrintObj と IID_IEditInterface m_CEditObj にそれぞれ接続します。QueryInterface (CCmdTarget::ExternalQueryInterface) のCCmdTarget実装では、このマップを使用してポインターを m_CPrintObj、要求されたときの m_CEditObj に戻ります。IID_IUnknownのエントリを含める必要はありません;フレームワークが、最初のインターフェイス (この場合は、m_CPrintObj) のマップを使用するIID_IUnknownの要求。

BEGIN_INTERFACE_PARTマクロ自動的にAddRefリリースおよびQueryInterface関数が宣言されても、まだそれらを実装する必要があります。:

ULONG までエクスポート CEditPrintObj::XEditObj::AddRef(){特価;METHOD_PROLOGUE (CEditPrintObj, EditObj)pThis - 戻る > ExternalAddRef();}ULONG までエクスポート CEditPrintObj::XEditObj::Release(){METHOD_PROLOGUE (CEditPrintObj, EditObj)pThis - 戻る > ExternalRelease();}HRESULT は数 CEditPrintObj::XEditObj::QueryInterface (をエクスポートします。REFIID iid、void まで ※ まで ※ ppvObj){METHOD_PROLOGUE (CEditPrintObj, EditObj)返す (HRESULT) pThis - > ExternalQueryInterface (& iid、ppvObj);}void までエクスポート CEditPrintObj::XEditObj::EditObject(){METHOD_PROLOGUE (CEditPrintObj, EditObj)・ ・「編集する」、オブジェクト、どんなことを意味.}

CEditPrintObj::CPrintObj の実装になる、上記の定義に CEditPrintObj::CEditObj のような。それは、(実際のところ、MFC および OLE 開発で以前これだった場合)、これらの関数を自動的に生成される可能性がありますマクロを作成することが可能ですが、マクロのコードの 1 つ以上の行を生成するときにブレークポイントを設定することは困難になります。このため、このコードを手動で展開されます。

メッセージのフレームワークの実装を使用してマップが行うには必要に応じていないものの数です。:

さらに、フレームワークは内部的にメッセージ マップを使用します。これにより、フレームワーク クラスから派生できますが既に特定のインターフェイスをサポートし、代替または追加するには、フレームワークによって提供されるインターフェイスを提供COleServerDocと言います。これは、フレームワークを完全にインターフェイス マップは、基本クラスから継承をサポートするという事実によって有効になります-なぜ begin_interface_map、2 番目のパラメーターとして、基本クラスの名前、理由。

特価;一般的に、mfc の組み込み OLE インターフェイスの実装を再利用によって、継承インターフェイス、mfc から埋め込みに特殊化ことはできません。これが不可能なためを含むCCmdTargetへのアクセスを取得するには、 METHOD_PROLOGUEマクロの使用-派生オブジェクトが意味するオフセットを修正 CCmdTargetから埋め込みオブジェクトの-オブジェクトを派生します。たとえば、XAdviseSink、 COleClientItemオブジェクトの先頭から指定したオフセットに依存するため、組み込みの XMyAdviseSink COleClientItem::XAdviseSinkMFC の実装から派生することはできませんつまり、(&N)。

ただし、MFC 実装のすべての関数は MFC の既定の動作をすることに委任できます。これは、MFC の実装ではIOleInPlaceFrame (XOleInPlaceFrame) (m_xOleInPlaceUIWindow の多くの機能にデリゲート) COleFrameHookクラスで行われます。このデザインは多くのインターフェイスを実装するオブジェクトの実行時のサイズを減らすために選ばれた;(方法 m_pParent 前のセクションで使用した場合など) は、バック ポインターの不要します。

集約とインターフェイス マップ

MFC はスタンドアロンの COM オブジェクトをサポートすることに加え、集約もサポートします。集計自体はここで議論にあまりにも複雑なトピックです。集計の詳細については、 OLE プログラマ リファレンスを参照してください。このメモが単にフレームワークとインターフェイス マップに建てられた集計のサポートについて説明します。

集計を使用するには、2 つの方法があります: (1) は集計をサポートする COM オブジェクトを使用して、(2) 別に集計することができますオブジェクトを実装します。これらの機能は「集約オブジェクトを使用する」と「オブジェクトは集約化」を参照することができます。両方の MFC をサポートします。

集約オブジェクトを使用してください。

集約オブジェクト、QueryInterface 機構に集計をネクタイにいくつかの方法であることが必要を使用するには。他の言葉では、ネイティブ オブジェクトの一部が、集約オブジェクトが動作する必要があります。どのようにこのネクタイは、MFC のインターフェイス マップ機構にか?入れ子になったオブジェクトは、IID に割り当てられている、 INTERFACE_PARTマクロに加えて、 CCmdTarget派生クラスの一部として集計オブジェクトを宣言することもできます。これを行うには、 INTERFACE_AGGREGATEマクロを使用します。これにより、インターフェイス マップ機構に統合するのには ( IUnknownへのポインターする必要がありますまたは派生クラス)、メンバー変数を指定します。CCmdTarget::ExternalQueryInterfaceが呼び出されると、ポインターが NULL でない場合は、フレームワークは自動的に集計オブジェクトのQueryInterfaceメンバー関数を呼び出します、 IIDを要求された場合は、 CCmdTargetオブジェクトによってサポートされているネイティブのIIDs の 1 つにないです。

INTERFACE_AGGREGATE マクロを使用するには、次の手順を実行します。:

  1. 集約オブジェクトへのポインターを格納するメンバー変数 (、 IUnknown ※) を宣言します。

  2. メンバー変数を名前で参照、インターフェイス マップには、 INTERFACE_AGGREGATEマクロを含める。

  3. (通常CCmdTarget::OnCreateAggregates) 中のいくつかの時点で、メンバー変数に NULL 以外の値の初期化します。

たとえば,

cAggrExample クラス: パブリック CCmdTarget{パブリック。特価;CAggrExample();保護。LPUNKNOWN m_lpAggrInner;仮想 BOOL OnCreateAggregates();DECLARE_INTERFACE_MAP()・ ・「ネイティブ」インターフェイスそのマクロ使用ここで};CAggrExample::CAggrExample(){m_lpAggrInner = NULL;}BOOL CAggrExample::OnCreateAggregates(){//正しい制御未知のワイヤーを集計m_lpAggrInner = CoCreateInstance (CLSID_Example、GetControllingUnknown()、CLSCTX_INPROC_SERVER、IID_IUnknown、(LPVOID ※) & m_lpAggrInner);場合 (m_lpAggrInner = = NULL)FALSE を返す;・ ・必要に応じて、ここにその他の集計オブジェクトを作成します。TRUE を返す;}BEGIN_INTERFACE_MAP (CAggrExample、CCmdTarget)//ネイティブ」INTERFACE_PART」エントリはここに行くINTERFACE_AGGREGATE (CAggrExample、m_lpAggrInner)END_INTERFACE_MAP()(&N)

m_lpAggrInnerコンス トラクターに NULL に初期化されます。フレームワークは、 QueryInterfaceの既定の実装で NULL メンバー変数を無視します。OnCreateAggregatesは、実際には、集計オブジェクトを作成するのには良い場所です。COleObjectFactoryの MFC 実装の外のオブジェクトを作成する場合は、それを明示的に呼び出す必要があります。集約オブジェクトの作成について説明するとCCmdTarget::OnCreateAggregatesとしてCCmdTarget::GetControllingUnknown量の集計を作成する理由は明らかになるだろう。

この手法、オブジェクトはその本来のインターフェイスに加えて集約オブジェクトをサポートするインターフェイスのすべてを与えます。のみの集計をサポートしているインターフェイスのサブセットにする場合は、 CCmdTarget::GetInterfaceHookをオーバーライドすることができます。この、非常に低レベルの hookability は、 QueryInterfaceのようなことができます。通常、場合は、集計をサポートしているすべてのインターフェイス。

オブジェクトが集約を

集約するオブジェクトには、 AddRefリリース、およびQueryInterfaceの実装は「制御未知」の委任する必要があります他の言葉は、オブジェクトの一部になり、 AddRefリリース、およびQueryInterfaceIUnknownから派生した別のオブジェクトに委任する必要があります。それが作成されると、オブジェクトには、それCOleObjectFactoryの実装に提供されてこの「制御不明」です。この実装を少量のオーバーヘッドを運ぶし、MFC この省略可能なので、いくつかのケースでは望ましくありません。集約するオブジェクトを有効にするには、あなたは、オブジェクトのコンス トラクターからCCmdTarget::EnableAggregationを呼び出す。

オブジェクトは集計を使用する場合、また、正しいパスを確認する必要があります「制御未知」の集計オブジェクト。通常、集計を作成するときこのIUnknownポインターをオブジェクトに渡されます。たとえば、pUnkOuter パラメーター「制御の不明な「 CoCreateInstanceで作成されたオブジェクトです。正しい「不明な制御」ポインター CCmdTarget::GetControllingUnknownを呼び出すことによって取得できます。その関数から返される値ただし、中にコンス トラクターは無効です。このため、それだけのCCmdTarget::OnCreateAggregates GetControllingUnknownからの戻り値、 COleObjectFactoryの実装から作成された場合でも信頼性の高いが、オーバーライドで、集計を作成することをお勧め。

また、オブジェクトが追加または人工の参照カウントを解放するとき、正しい参照カウントを操作することが重要です。このようなことを確認するには、常にExternalAddRefExternalReleaseの代わりにInternalReleaseInternalAddRefを呼び出します。集約をサポートするクラスにInternalReleaseまたはInternalAddRefを呼び出すことはまれです。

参考資料

Ole を使用して、独自のインターフェイスを定義または OLE インターフェイスのフレームワークの実装をオーバーライドするなど、高度な使用法は、基になるインターフェイス マップ機構が必要です。

このセクションに各マクロとこれらの拡張機能を実装するために使用する Api について説明します。

CCmdTarget::EnableAggregation-機能説明

void EnableAggregation();

特価;この型のオブジェクトは OLE の集計をサポートする場合は、派生クラスのコンス トラクターでこの関数を呼び出します。これは、集約可能オブジェクトに必要な IUnknown 機能を準備します。(&N)。

CCmdTarget::ExternalQueryInterface-機能説明

DWORD ExternalQueryInterface (const void まで ※ lpIID, LPVOID まで ※ ppvObj);

lpIID

IID (QueryInterface を最初の引数) への far ポインター

ppvObj

※ IUnknown へのポインター (2 番目の引数に QueryInterface)

特価;この関数 IUnknown の実装では、各インターフェイスに対してクラスを呼び出しを実装します。この関数は、オブジェクトのインターフェイス マップに基づいて QueryInterface、標準データ駆動実装を提供します。戻り値が HRESULT にキャストする必要は。オブジェクトを集約する場合は、この関数は、「制御の IUnknown」ローカル インターフェイス マップを使用する代わりに呼び出します(&N)。

CCmdTarget::ExternalAddRef-機能説明

DWORD ExternalAddRef();

特価;この関数:addref の実装では、各インターフェイスに対してクラスを呼び出しを実装します。戻り値は、オブジェクトの新しい参照カウントです。オブジェクトを集約する場合は、この関数は「制御の IUnknown」ローカルの参照カウントを操作するのではなく呼び出します(&N)。

CCmdTarget::ExternalRelease-機能説明

DWORD ExternalRelease();

特価;この関数 iunknown::release の実装では、各インターフェイスに対してクラスを呼び出しを実装します。戻り値は、オブジェクトの新しい参照カウントを示します。オブジェクトを集約する場合は、この関数は「制御の IUnknown」ローカルの参照カウントを操作するのではなく呼び出します(&N)。

DECLARE_INTERFACE_MAP-マクロの説明

DECLARE_INTERFACE_MAP

特価;このマクロは、インターフェイス マップがCCmdTargetから派生した任意のクラスで使用します。多くのDECLARE_MESSAGE_MAPと同じように使用します。このマクロ呼び出しヘッダーでは、通常のクラス定義に配置する必要があります (。H) ファイル。DECLARE_INTERFACE_MAPクラスのインターフェイス マップ実装ファイルで定義する必要があります (。CPP) のBEGIN_INTERFACE_MAPEND_INTERFACE_MAPのマクロ(&N)。

BEGIN_INTERFACE_PART と END_INTERFACE_PART-マクロの説明

BEGIN_INTERFACE_PART (localClassiface;

END_INTERFACE_PART (localClass

localClass

インターフェイスを実装するクラスの名前

iface

このクラスを実装するインターフェイスの名前

特価;クラスが実装する各インターフェイスに対しては、 BEGIN_INTERFACE_PARTEND_INTERFACE_PARTのペアが必要があります。これらのマクロは、そのクラスの埋め込みメンバー変数として定義する OLE インターフェイスから派生したローカル クラスを定義します。AddRefリリース、およびQueryInterfaceのメンバーは自動的に宣言されます。実装されるインターフェイスの一部、他のメンバー関数の宣言を含める必要があります (これらの宣言には、 BEGIN_INTERFACE_PARTEND_INTERFACE_PARTのマクロの間に配置されます)(&N)。

Iface引数は、 IAdviseSink、またはIPersistStorage (カスタム インターフェイスなど) を実装する、OLE インターフェイスです。

LocalClass引数は、定義は、ローカル クラスの名前です。' X' の名前に自動的に付加されます。この名前付け規則は、同じ名前のグローバル クラスとの衝突を避けるために使用されます。また、埋め込みメンバーは、 localClass名以外の名前は 'm_x' で付きます。

たとえば:

BEGIN_INTERFACE_PART (MyAdviseSink、IAdviseSink)特価;STDMETHOD_(void,OnDataChange) (LPFORMATETC、LPSTGMEDIUM);STDMETHOD_(void,OnViewChange) (DWORD、長い);STDMETHOD_(void,OnRename)(LPMONIKER);STDMETHOD_(void,OnSave)();STDMETHOD_(void,OnClose)();END_INTERFACE_PART(MyAdviseSink)(&N)

iAdviseSink から派生した XMyAdviseSink と呼ばれるローカル クラスを定義すると、それが宣言されているクラスのメンバーと呼ばれる m_xMyAdviseSink.Note:

特価;STDMETHOD_で始まる行は、本質的には OLE2 からコピーされます。H とわずかに変更します。OLE2 からコピーします。H を解決するは難しいですエラーを減らすことができます。(&N)。

BEGIN_INTERFACE_MAP と END_INTERFACE_MAP-マクロの説明

BEGIN_INTERFACE_MAP ([クラス]baseClass

END_INTERFACE_MAP

[クラス]

インターフェイス マップで定義するクラス

baseClass

[クラス]から派生元のクラス。

の発言:BEGIN_INTERFACE_MAPEND_INTERFACE_MAPのマクロの実装ファイルで実際には、インターフェイス マップを定義に使用されます。実装されている各インターフェイスの 1 つまたは複数のINTERFACE_PARTマクロ呼び出しです。クラスを使用して各集計の場合、ある 1 つのINTERFACE_AGGREGATEマクロの呼び出し。

INTERFACE_PART ? マクロの説明

INTERFACE_PART ([クラス]iid、 localClass

[クラス]

インターフェイス マップを含む、クラスの名前。

iid

埋め込みクラスにマップするには、 IID

localClass

(以下の 'X') ローカル クラスの名前

特価;このマクロは、 BEGIN_INTERFACE_MAPマクロとEND_INTERFACE_MAPマクロの間をオブジェクトがサポートする各インターフェイスに対して使用されます。[クラス]およびlocalClassでクラスのメンバーに IID をマップできます。'M_x' にlocalClassを自動的に追加されます。1 つ以上のIIDを 1 つのメンバーに関連付けられていることに注意してください。「最派生」インターフェイスのみを実装しているし、すべての中間インタ フェースも提供したい場合に便利です。これの良い例は、 IOleInPlaceFrameWindowインターフェイスです。その階層はこのように見える(&N):

IUnknown特価;IOleWindowIOleUIWindowIOleInPlaceFrameWindow(&N)

IOleInPlaceFrameWindowオブジェクトを実装する場合は、これらのインターフェイスのQueryInterfaceクライアント可能性があります: IOleUIWindowIOleWindow、またはIUnknown、「最派生"インターフェイスIOleInPlaceFrameWindow (1 つは実際に実装する) ほか。これを処理するには、1 つ以上のINTERFACE_PARTマクロそれぞれとすべての基本インターフェイスは、 IOleInPlaceFrameWindowインターフェイスにマップするのに使用することができます。

クラス定義ファイル:

BEGIN_INTERFACE_PART (CMyFrameWindow, IOleInPlaceFrameWindow)

クラスの実装ファイルで:

BEGIN_INTERFACE_MAP (CMyWnd、CFrameWnd)特価;INTERFACE_PART (CMyWnd、IID_IOleWindow、MyFrameWindow)INTERFACE_PART (CMyWnd、IID_IOleUIWindow、MyFrameWindow)INTERFACE_PART (CMyWnd、IID_IOleInPlaceFrameWindow、MyFrameWindow)END_INTERFACE_MAP(&N)

フレームワークの IUnknown は常に必要があるので面倒します。

INTERFACE_PART ? マクロの説明

INTERFACE_AGGREGATE ([クラス]theAggr

[クラス]

インターフェイス マップを含む、クラスの名前,

theAggr

集計には、メンバー変数の名前。

特価;このマクロを使用して、クラスが集約オブジェクトを使用するいると、フレームワークを指示します。それ間のBEGIN_INTERFACE_PARTEND_INTERFACE_PARTのマクロを表示する必要があります。集約オブジェクトのIUnknownから派生した、別のオブジェクトです。集計とは、 INTERFACE_AGGREGATEマクロを使用して、集計のサポート オブジェクトによって直接サポートするようにすべてのインターフェイスをすることができます。TheAggr引数が (直接または間接的に) IUnknownから派生クラスのメンバー変数の名前だけです。INTERFACE_AGGREGATEのすべてのマクロINTERFACE_PARTマクロ、インターフェイス マップを配置するときに従う必要があります。(&N)。

番号順テクニカル ノート|nbsp;カテゴリ別テクニカル ノート(&N)

Index