HOWTO:改写 MFC 应用程序中已实现的 COM 接口 (Interface)

本文的发布号曾为 CHS141277
本文已归档。它按“原样”提供,并且不再更新。
概要
在 MFC 应用程序中,可以按类改写已有接口或提供附加接口。在这种情况下,改写接口和替换接口是同义的。本文中的示例说明如何在保留原始接口实现时按类改写接口,这样新接口的实现就是到原始接口的一个代理。

对 IDispatch 的实现的改写是一种特殊情况,本文不做处理。本文以下说明如何在 MFC 中改写 Idispatch:
140616MFCDISP:替换 MFC 的 IDispatch 实现
更多信息
下列步骤将改写由 Control Wizard 创建的默认 OLE Control 的 IOleObject 实现。

  1. 要为控件添加 IOleObject 实现的声明,请将下列代码添加到 ColeControl 衍生类的头文件中 :
          // Interface Maps      protected:           // IOleObject           BEGIN_INTERFACE_PART(MyOleObject, IOleObject)               INIT_INTERFACE_PART(CIOleOverCtrl, MyOleObject)               STDMETHOD(SetClientSite)(LPOLECLIENTSITE);               STDMETHOD(GetClientSite)(LPOLECLIENTSITE*);               STDMETHOD(SetHostNames)(LPCOLESTR, LPCOLESTR);               STDMETHOD(Close)(DWORD);               STDMETHOD(SetMoniker)(DWORD, LPMONIKER);               STDMETHOD(GetMoniker)(DWORD, DWORD, LPMONIKER*);               STDMETHOD(InitFromData)(LPDATAOBJECT, BOOL, DWORD);               STDMETHOD(GetClipboardData)(DWORD, LPDATAOBJECT*);               STDMETHOD(DoVerb)(LONG, LPMSG, LPOLECLIENTSITE, LONG, HWND,                       LPCRECT);               STDMETHOD(EnumVerbs)(IEnumOLEVERB**);               STDMETHOD(Update)();               STDMETHOD(IsUpToDate)();               STDMETHOD(GetUserClassID)(CLSID*);               STDMETHOD(GetUserType)(DWORD, LPOLESTR*);               STDMETHOD(SetExtent)(DWORD, LPSIZEL);               STDMETHOD(GetExtent)(DWORD, LPSIZEL);               STDMETHOD(Advise)(LPADVISESINK, LPDWORD);               STDMETHOD(Unadvise)(DWORD);               STDMETHOD(EnumAdvise)(LPENUMSTATDATA*);               STDMETHOD(GetMiscStatus)(DWORD, LPDWORD);               STDMETHOD(SetColorScheme)(LPLOGPALETTE);           END_INTERFACE_PART(MyOleObject)      DECLARE_INTERFACE_MAP();
    这样,就为控件类添加了嵌套类 XmyOleObject。 注意:这些宏声明所声明的接口方法中包括 Iunknown,所以也必须实现 IUnknown 方法。
  2. 将 INTERFACE_PART 宏添加到控件的实现文件中,就可以将 IOleObject 接口添加到控件的接口映射中:
          BEGIN_INTERFACE_MAP(CIOleOverCtrl, COleControl)         INTERFACE_PART(CIOleOverCtrl, IID_IOleObject, MyOleObject)      END_INTERFACE_MAP()
    用你的控件名称替代 CIOleOverCtrl,用支持 IOleObject 的嵌套类的名称替代 MyOleObject。
  3. 为实现你所声明的接口的所有方法,将下列代码添加到控件的实现文件中:
          STDMETHODIMP_(ULONG) CIOleOverCtrl::XMyOleObject::AddRef()      {          METHOD_MANAGE_STATE(CIOleOverCtrl, MyOleObject)          ASSERT_VALID(pThis);          return pThis->m_xOleObject.AddRef();      }      STDMETHODIMP_(ULONG) CIOleOverCtrl::XMyOleObject::Release()      {          METHOD_MANAGE_STATE(CIOleOverCtrl, MyOleObject)          ASSERT_VALID(pThis);          return pThis->m_xOleObject.Release ();      }      STDMETHODIMP CIOleOverCtrl::XMyOleObject::QueryInterface(          REFIID iid, LPVOID far* ppvObj)      {          METHOD_MANAGE_STATE(CIOleOverCtrl, MyOleObject)          ASSERT_VALID(pThis);          return pThis->m_xOleObject.QueryInterface ( iid,  ppvObj);      }      STDMETHODIMP      CIOleOverCtrl::XMyOleObject::SetClientSite(LPOLECLIENTSITE      pClientSite)      {          METHOD_MANAGE_STATE(CIOleOverCtrl, MyOleObject)             ASSERT_VALID(pThis);          return pThis->m_xOleObject.SetClientSite ( pClientSite );      }      ...
其它方法遵循相同的模式,其中 CIOleOverCtrl 是控件名称,XMyOleObject 是支持 IoleObject 的嵌套类的名称,而 m_xMyOleObject 是通过从所支持的接口中去掉 I 并添加 m_x 得到的。


注意这些方法只是将调用简单地传递到原有的 IOleObject 实现。但是,这并不是必须的;你可以在原有实现上添加功能、代理原有实现或根本不代理。
参考
技术注释 #38 和 #39。
属性

文章 ID:141277 - 上次审阅时间:03/01/2014 07:17:09 - 修订版本: 2.0

  • Microsoft Foundation Class Library 4.2
  • kbnosurvey kbarchive kbhowto kbvc400 kbmfc kbvc500 kbvc600 kbvc200 kbdss kbarchitecture kbole kbgrpdsmfcatl kbactivex kbcomt KB141277
反馈