收藏 分享(赏)

09-2COM开发+MFC+ATL.ppt

上传人:czsj190 文档编号:4523866 上传时间:2019-01-01 格式:PPT 页数:89 大小:502KB
下载 相关 举报
09-2COM开发+MFC+ATL.ppt_第1页
第1页 / 共89页
09-2COM开发+MFC+ATL.ppt_第2页
第2页 / 共89页
09-2COM开发+MFC+ATL.ppt_第3页
第3页 / 共89页
09-2COM开发+MFC+ATL.ppt_第4页
第4页 / 共89页
09-2COM开发+MFC+ATL.ppt_第5页
第5页 / 共89页
点击查看更多>>
资源描述

1、COM开发,潘爱民 2003-11-7 http:/ SDK和MFC介绍 MFC对COM的支持 用MFC开发COM组件 ATL对COM的支持 用ATL开发COM组件 布置作业,Win32 SDK: Windows程序结构,入口函数WinMain 应用初始化 主窗口的创建及显示 消息分发循环 程序结束处理,Win32 SDK对COM的支持,Win32 SDK包括COM库函数的支持,利用宏描述接口,DECLARE_INTERFACE_(IClassFactory, IUnknown)STDMETHOD(QueryInterface) (THIS_REFIID riid,LPVOID FAR* pp

2、vObj) PURE;STDMETHOD_(ULONG,AddRef) (THIS) PURE;STDMETHOD_(ULONG,Release) (THIS) PURE;STDMETHOD(CreateInstance) (THIS_LPUNKNOWN pUnkOuter,REFIID riid,LPVOID FAR* ppvObject) PURE;STDMETHOD(LockServer)(THIS_ BOOL fLock) PURE;,VC提供的用于描述接口的宏,MFC基础,应用类 AfxGetApp CWinApp:InitInstance CWinApp:ExitInstance

3、CWinApp:OnIdle CWinApp:Run CWnd *m_pMainWnd 窗口类 AfxGetMainWnd,MFC的消息处理机制 消息映射表,在CWnd派生类定义中加入声明: DECLARE_MESSAGE_MAP()在类的实现文件中加入表和表项的定义: BEGIN_MESSAGE_MAP(theClass, baseClass)END_MESSAGE_MAP,消息映射表示例,BEGIN_MESSAGE_MAP(theClass, baseClass)/AFX_MSG_MAP(theClass)ON_WM_SETFOCUS()ON_WM_CREATE()ON_WM_DESTRO

4、Y()ON_WM_CLOSE()ON_WM_SIZE()ON_MESSAGE(WM_COMMANDHELP, OnCommandHelp)ON_MESSAGE(WM_HELPHITTEST, OnHelpHitTest)ON_UPDATE_COMMAND_UI(ID_VIEW_STATUS_BAR, OnUpdateControlBarMenu)ON_NOTIFY_EX_RANGE(TTN_NEEDTEXTW, 0, 0xFFFF, OnToolTipText)/AFX_MSG_MAP END_MESSAGE_MAP,MFC应用类型,常规应用:MDI应用、SDI应用、基于对话框程序 DLL应用

5、:静态连接MFC库的正规DLL、动态连接MFC库的正规DLL、MFC扩展DLL 其他应用: 支持OLE服务或者包容器的SDI应用 支持OLE服务或者包容器的MDI应用 支持自动化(Automation)服务的SDI或者MDI程序 ActiveX控制应用(OCX应用),MFC库结构(参照4.2版本),MFC对COM应用的支持,用嵌套类实现COM接口,class CDictionary /构造函数和析构函数HRESULT _stdcall QueryInterface(REFIID iid, void* ppvObj);ULONG _stdcall AddRef(); ULONG _stdcall

6、 Release(); class XDictionaryObj : public IDictionary public:CDictionary * m_pParent;virtual HRESULT _stdcall QueryInterface(REFIID iid, void* ppvObj);virtual ULONG _stdcall AddRef(); virtual ULONG _stdcall Release(); virtual BOOL _stdcall Initialize();.virtual void _stdcall FreeLibrary(); m_diction

7、aryObj;,未完,用嵌套类实现COM接口(续一),class XSpellCheckObj : public ISpellCheck public:CDictionary * m_pParent;virtual HRESULT _stdcall QueryInterface(REFIID iid, void* ppvObj);virtual ULONG _stdcall AddRef(); virtual ULONG _stdcall Release(); virtual BOOL _stdcall CheckWord (String word, String *); m_spellChe

8、ckObj;private :struct DictWord *m_pData;char *m_DictFilename128;int m_Ref ;int m_nWordNumber, m_nStructNumber; ;,续,用嵌套类实现COM接口(续二),CDictionary:CDictionary() . / Initializtionm_dictionaryObj. m_pParent = this;m_spellCheckObj. m_pParent = this; ,用嵌套类实现COM接口(续三),HRESULT CDictionary:QueryInterface(const

9、 IID ,用嵌套类实现COM接口(续四),ULONG CDictionary:XDictionaryObj:QueryInterface(const IID ,“用嵌套类实现COM接口”原理,m_pData m_DictFilename128 m_Ref m_nWordNumber m_nStructNumber,QueryInterface AddRef Release .,m_dictionaryObj,m_spellCheckObj,QueryInterface AddRef Release ,QueryInterface AddRef Release ,Vtable for IDic

10、tionary,Vtable for ISpellCheck,CDictionary,vptr,vptr,CDictionary的非虚函数,MFC:接口映射表,CCmdTarget类 CCmdTarget:m_dwRef为引用计数 接口映射表与消息映射表非常类似 接口映射表:记录了CCmdTarget类中每一个嵌套类的接口ID以及接口vtable与父类this指针之间的偏移量 offsetof宏:成员类与父类之间的偏移值,DECLARE_INTERFACE_MAP,#define DECLARE_INTERFACE_MAP() private: static const AFX_INTERFA

11、CEMAP_ENTRY _interfaceEntries; protected: static AFX_DATA const AFX_INTERFACEMAP interfaceMap; static const AFX_INTERFACEMAP* PASCAL _GetBaseInterfaceMap(); virtual const AFX_INTERFACEMAP* GetInterfaceMap() const; ,struct AFX_INTERFACEMAP_ENTRY const void* piid; size_t nOffset; ;,struct AFX_INTERFAC

12、EMAP #ifdef _AFXDLLconst AFX_INTERFACEMAP* (PASCAL* pfnGetBaseMap)(); #elseconst AFX_INTERFACEMAP* pBaseMap; #endifconst AFX_INTERFACEMAP_ENTRY* pEntry; ;,接口映射表定义,BEGIN_INTERFACE_MAP(CDictionary, CCmdTarget)INTERFACE_PART(CDictionary, IID_IDictionary, Dictionary)INTERFACE_PART(CDictionary, IID_ISpel

13、lCheck, SpellCheck) END_INTERFACE_MAP(),接口映射表的宏定义,#define BEGIN_INTERFACE_MAP(theClass, theBase) const AFX_INTERFACEMAP* PASCAL theClass:_GetBaseInterfaceMap() return ,MFC版本的字典对象类定义,class CDictionary : public CCmdTarget DECLARE_DYNCREATE(CDictionary) CDictionary(); / protected constructor used by dy

14、namic creationDECLARE_INTERFACE_MAP()/ IDictionaryBEGIN_INTERFACE_PART(Dictionary, IDictionary)INIT_INTERFACE_PART(CDictionary, Dictionary)STDMETHOD_(BOOL, Initialize)();STDMETHOD_(void, FreeLibrary)();END_INTERFACE_PART_STATIC(Dictionary) / ISpellCheckBEGIN_INTERFACE_PART(SpellCheck, ISpellCheck)IN

15、IT_INTERFACE_PART(CDictionary, SpellCheck)STDMETHOD_(BOOL, CheckWord)(LPOLESTR, LPOLESTR *);END_INTERFACE_PART_STATIC(SpellCheck) ;,MFC版本的字典对象类实现,STDMETHODIMP_(ULONG) CDictionary:XDictionary:AddRef() METHOD_PROLOGUE_EX_(CDictionary, Dictionary)return pThis-ExternalAddRef(); METHOD_PROLOGUE_EX_宏定义:#d

16、efine METHOD_PROLOGUE_EX(theClass, localClass) theClass* pThis = (theClass*)(BYTE*)this - m_nOffset); AFX_MANAGE_STATE(pThis-m_pModuleState) pThis; / avoid warning from compiler ,CCmdTarget类实现IUnknown,public:/ data used when CCmdTarget is made OLE awarelong m_dwRef;LPUNKNOWN m_pOuterUnknown; / exter

17、nal controlling unknown if != NULLDWORD m_xInnerUnknown; / place-holder for inner controlling unknownpublic:/ advanced operationsvoid EnableAggregation(); / call to enable aggregationvoid ExternalDisconnect(); / forcibly disconnectLPUNKNOWN GetControllingUnknown();/ get controlling IUnknown for aggr

18、egate creation,CCmdTarget类实现IUnknown(续),public:/ these versions do not delegate to m_pOuterUnknownDWORD InternalQueryInterface(const void*, LPVOID* ppvObj);DWORD InternalAddRef();DWORD InternalRelease();/ these versions delegate to m_pOuterUnknownDWORD ExternalQueryInterface(const void*, LPVOID* ppv

19、Obj);DWORD ExternalAddRef();DWORD ExternalRelease();,CCmdTarget中QueryInterface实现,DWORD CCmdTarget:InternalQueryInterface(const void* iid, LPVOID* ppvObj) / check local interfacesif (*ppvObj = GetInterface(iid) != NULL) / interface was found - add a referenceExternalAddRef();return S_OK;/ check aggre

20、gatesif (*ppvObj = QueryAggregates(iid) != NULL)return S_OK;/ interface ID not found, fail the callreturn (DWORD)E_NOINTERFACE; ,CCmdTarget中ExternalXXX成员实现,DWORD CCmdTarget:ExternalAddRef() / delegate to controlling unknown if aggregatedif (m_pOuterUnknown != NULL)return m_pOuterUnknown-AddRef();ret

21、urn InternalAddRef(); DWORD CCmdTarget:ExternalRelease() / ./ QueryInterface that is exported to normal clients DWORD CCmdTarget:ExternalQueryInterface(const void* iid, LPVOID* ppvObj) / delegate to controlling unknown if aggregatedif (m_pOuterUnknown != NULL)return m_pOuterUnknown-QueryInterface(*(

22、IID*)iid, ppvObj);return InternalQueryInterface(iid, ppvObj); ,嵌套类内部实现IUnknown的成员函数,STDMETHODIMP_(ULONG) CDictionary:XDictionary:QueryInterface (const void* iid, LPVOID* ppvObj) METHOD_PROLOGUE_EX_(CDictionary, Dictionary)return pThis-ExternalQueryInterface (iid, ppvObj); ,COM引出函数和类厂实现,在AppWizard中选中

23、“Automation”检查框STDAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID* ppv) AFX_MANAGE_STATE(AfxGetStaticModuleState();return AfxDllGetClassObject(rclsid, riid, ppv); STDAPI DllCanUnloadNow(void) AFX_MANAGE_STATE(AfxGetStaticModuleState();return AfxDllCanUnloadNow(); / by exporting DllRegiste

24、rServer, you can use regsvr.exe STDAPI DllRegisterServer(void) AFX_MANAGE_STATE(AfxGetStaticModuleState();COleObjectFactory:UpdateRegistryAll();return S_OK; ,COleObjectFactory,通用的类厂,实现了IClassFactory2接口 COleObjectFactory的主要信息是对象的CLSID和对象的类型信息。 它利用MFC的动态对象创建机制: DECLARE_DYNCREATE 对象方面的支持: DECLARE_OLECR

25、EATE(.),定义如下 #define DECLARE_OLECREATE(class_name) public: static AFX_DATA COleObjectFactory factory; static AFX_DATA const GUID guid; ,MFC中组件对象的创建支持,DECLARE_OLECREATE(.) IMPLEMENT_OLECREATE #define IMPLEMENT_OLECREATE(class_name, external_name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) AFX_DATADEF

26、 COleObjectFactory class_name:factory(class_name:guid, RUNTIME_CLASS(class_name), FALSE, _T(external_name); AFX_COMDAT const AFX_DATADEF GUID class_name:guid = l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8 ; 状态结构:AFX_MODULE_STATE,除了一些基本的全局信息,还包括一个类厂表。 DllGetClassObject-AfxDllGetClassObject-AfxGetModuleS

27、tate进一步得到类厂表 类厂对象的构造函数和析构函数维护类厂表,用MFC开发COM应用,利用AppWizard创建COM程序工程框架利用ClassWizard添加COM对象类,AppWizard创建COM工程(一),AppWizard创建COM工程(二),AppWizard创建COM工程(三),BOOL CDictCompApp:InitInstance() / Register all OLE server (factories) as running. / This enables the/ OLE libraries to create objects from other appli

28、cations.COleObjectFactory:RegisterAll();return TRUE; ,ClassWizard添加COM对象类(一),ClassWizard添加COM对象类(二),CDictionaryObj声明中加入接口定义,BEGIN_INTERFACE_PART(Dictionary, IDictionary)INIT_INTERFACE_PART(CDictionary, Dictionary)STDMETHOD_(BOOL, Initialize)();STDMETHOD_(BOOL, LoadLibrary)(LPOLESTR);STDMETHOD_(BOOL,

29、 InsertWord)(LPOLESTR, LPOLESTR);STDMETHOD_(void, DeleteWord)( LPOLESTR);STDMETHOD_(BOOL, LookupWord)(LPOLESTR, LPOLESTR *);STDMETHOD_(BOOL, RestoreLibrary)(LPOLESTR);STDMETHOD_(void, FreeLibrary)();END_INTERFACE_PART_STATIC(Dictionary) / ISpellCheckBEGIN_INTERFACE_PART(SpellCheck, ISpellCheck)INIT_

30、INTERFACE_PART(CDictionary, SpellCheck)STDMETHOD_(BOOL, CheckWord)(LPOLESTR, LPOLESTR *);END_INTERFACE_PART_STATIC(SpellCheck)DECLARE_INTERFACE_MAP(),CDictionaryObj类实现文件中 加入相应的定义,extern “C“ const IID IID_Dictionary = 0x54bf6568, 0x1007, 0x11d1, 0xb0, 0xaa, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00 ;extern

31、“C“ const IID IID_SpellCheck = 0x54bf6569, 0x1007, 0x11d1, 0xb0, 0xaa, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00 ;BEGIN_INTERFACE_MAP(CDictionaryObj, CCmdTarget)INTERFACE_PART(CDictionaryObj, IID_IDictionary, Dictionary)INTERFACE_PART(CDictionaryObj, IID_ISpellCheck, SpellCheck) END_INTERFACE_MAP(),类厂支持,在C

32、DictionaryObj声明中加入: DECLARE_OLECREATE(CDictionaryObj) 在CDictionaryObj实现文件中加入: / 54BF6567-1007-11D1-B0AA-444553540000 IMPLEMENT_OLECREATE(CDictionaryObj, “Dictionary.Object “, 0x54bf6567, 0x1007, 0x11d1, 0xb0, 0xaa, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00),MFC对连接和事件的支持,用MFC实现源对象,创建工程支持COM 定义出接口编辑.odl文件 利用

33、MFC宏加入连接点声明以及连接点对象的定义 在对象构造函数中调用EnableConnections(); 在接口映射表中加入接口IConnectionPointContainer的表项,再加入连接映射表 定义连接点类的虚函数(至少为GetIID) 加入事件激发函数,用MFC在客户程序中实现接收器,初始化 AfxOleInit 定义出接口成员类 实现出接口成员类 创建源对象 建立连接和取消连接 完成可触发事件的动作,用MFC实现的例子,ATL介绍,ATL实现COM的机制完全不同于MFC 使用多继承技术实现多个接口 支持多线程 实现QueryInterface用到了特殊的技术 创建对象机制不同于以

34、往的技术 优化,ATL概况,封装了一些数据类型 CComBSTR、CComVariant、CComPtr,等 实现COM接口和COM对象 接口映射表、对象映射表,等 窗口的支持 CWindow、CWindowImpl、CDialogImpl,等 其他COM特征的支持 永久性支持 连接点支持 集合对象和枚举器对象 ActiveX control and container 等,CComBSTR,封装了BSTR类型 提供了大量便利的字符串操作 构造函数 各种操作符以及一般的字符串操作 对于流(stream)的支持 在需要BSTR的地方,都可以用CComBSTR来代替 注意owership,CCom

35、Variant,封装了VARIANT属性 提供了常用的操作 构造函数 各种操作符以及一般的管理操作 对于流(stream)的支持 在需要VARIANT的地方,都可以用CComVARIANT来代替,CComPtr、CComQIPtr,Smart pointer template template class CComPtr class CComQIPtr public: public:T* p; T* p; . ; ; 优点: 自动管理AddRef/Release 在大多数情况下,可以当作接口指针来使用 注意:禁止调用“-Release”和“-AddRef”,CComDispatchDriver

36、,封装了IDispatch接口 除了对接口指针的管理之外,有下面的功能: 属性访问函数: GetIDOfName/ GetProperty/ PutProperty GetPropertyByName/ PutPropertyByName 方法访问函数: by DISPID:Invoke0/Invoke1/Invoke2/InvokeN by Name:Invoke0/Invoke1/Invoke2/InvokeN 两个静态函数: By DISPID:GetProperty/PutProperty,ATL的类层次,CMyClass,CComObjectRootBase,CComObjectRo

37、otEx,IXxxImpl,IMyItf1,IMyItf2,CComObject等,CComXxxThreadModel,CComObjectRootBase,ObjectMain static InternalQueryInterface OuterAddRef/OuterRelease/OuterQueryInterface InternalFinalConstructAddRef/ InternalFinalConstructRelease 其他一些静态函数 联合: unionlong m_dwRef;IUnknown* m_pOuterUnknown;,ATL对象的线程模型,用到了tr

38、ait技术 通过编译时刻的类型提供just thread-safe enough CComSingleThreadModel CComMultiThreadModel CComMultiThreadNoCS 提供了两个静态成员函数和三个typedef Increment、Decrement AutoCriticalSection、CriticalSection、ThreadModelNoCS,ATL对象实现引用计数,CComObjectRootEx InternalAddRef InternalRelease 作用在匿名联合的m_dwRef成员上 CComObjectRootEx定义了一把锁

39、锁的类型为AutoCriticalSection 对锁的封装ObjectLock,wrapper 用于未被聚合的情况下,ATL对象实现QueryInterface,Table-driven QueryInterface Interface MapBEGIN_COM_MAP(class)COM_INTERFACE_ENTRY(itf)END_COM_MAP 表中每一项struct _ATL_INTMAP_ENTRY const IID* piid;DWORD dw;_ATL_CREATORARGFUNC *pFunc;,ATL实现的接口类,IDispatchImpl IPersistStream

40、InitImpl IConnectionPointContainerImpl 举例: template class IDispatchImpl : public T ; template class IConnectionPointContainerImpl : public IConnectionPointContainer.;class CMyObject : public IDispatchImpl,public IConnectionPointContainerImpl ;,真正的ATL对象类,决定这个COM对象如何被分配,是否被聚合等 区别: 线程模型是以每个类为基础的,per-cl

41、ass,可以封装到基类中 对象的生命周期和身份标识是以每个对象实例为基础的,per-object,要延后到最终的派生类做出决定 CComObject类: template CComObject : public Base ; 支持聚合:class CComAggObject; 支持聚合: class CComPolyObject; template CComObjectCached : public Base ; template CComObjectNoLock : public Base ; template CComObjectGlobal : public Base ; templat

42、e CComObjectStack : public Base ;,ATL对象的创建,两个步骤: 使用CRT的构造器 FinalConstruct 对应于FinalConstruct有FinalRelease 举例: CMyClassFactory:CreateInstance() CComObject *pObj = new CComObject;.pObj-InternalFinalConstructAddRef();HRESULT hr = FinalConstruct();pObj-InternalFinalConstructRelease(); ,ATL Creators,每个cre

43、ator类有一个静态CreateInstance函数: HRESULT WINAPI CreateInstance(void* pv, REFIID riid, LPVOID* ppv); 举例: template class CComCreator public:static HRESULT WINAPI CreateInstance(void* pv, REFIID riid, LPVOID* ppv) T *pObj = new T(pv);.pObj-InternalFinalConstructAddRef();HRESULT hr = FinalConstruct();pObj-In

44、ternalFinalConstructRelease();hr = p-QueryInterface(riid, ppv); ;,ATL Creators(续),其他的creator类有 CComCreator2 根据pv参数是否为null从两个对象类中择一 CComFailCreator 假的创建类 在CMyObject类中定义一个类型_CreatorClass,例如 typedef CComCreator _CreatorClass; CComCoClass定义: template class CComCoClass public:template static HRESULT Crea

45、teInstance(IUnknown* punkOuter, Q* pp) return T:_CreatorClass:CreateInstance(punkOuter, _uuidof(Q), (void *)pp); ;,聚合情况下对象结构图,CMyClass,CComObjectRootBase,CComObjectRootEx,IXxxImpl,IMyItf1,IMyItf2,CComContainedObject,CComXxxThreadModel,ATL中对象聚合的实现,template class CComAggObject :public IUnknown,public

46、CComObjectRootEx public :STDMETHOD_(ULONG, AddRef)() STDMETHOD_(ULONG, Release)() STDMETHOD(QueryInterface)(REFIID iid, void * ppvObject)CComContainedObject m_contained; ;,非委托IUnknown,委托IUnknown,ATL中对象聚合的实现(续),template /Base must be derived from CComObjectRoot class CComContainedObject : public Base

47、 public:typedef Base _BaseClass;CComContainedObject(void* pv) m_pOuterUnknown = (IUnknown*)pv;STDMETHOD_(ULONG, AddRef)() return OuterAddRef();STDMETHOD_(ULONG, Release)() return OuterRelease();STDMETHOD(QueryInterface)(REFIID iid, void * ppvObject) / 调用 OuterQueryInterface(iid, ppvObject); IUnknown

48、* GetControllingUnknown() ;,/ CComObjectRootBase基类中联合成员m_pOuterUnknown起作用,接口映射表项类型,COM_INTERFACE_ENTRY COM_INTERFACE_ENTRY_IID(iid, x) COM_INTERFACE_ENTRY2(x, x2) COM_INTERFACE_ENTRY2_IID(iid, x, x2) COM_INTERFACE_ENTRY_FUNC(iid, dw, func) COM_INTERFACE_ENTRY_FUNC_BLIND(dw, func) COM_INTERFACE_ENTRY_TEAR_OFF(iid, x) COM_INTERFACE_ENTRY_CACHED_TEAR_OFF(iid, x, punk) COM_INTERFACE_ENTRY_AGGREGATE(iid, punk) COM_INTERFACE_ENTRY_AGGREGATE_BLIND(punk) COM_INTERFACE_ENTRY_CHAIN(classname),

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 网络科技 > C/C++资料

本站链接:文库   一言   我酷   合作


客服QQ:2549714901微博号:道客多多官方知乎号:道客多多

经营许可证编号: 粤ICP备2021046453号世界地图

道客多多©版权所有2020-2025营业执照举报