COM开发 潘爱民 http://www.icst.pku.edu.cn/compcourse 内容 ? Win32 SDK和MFC介绍 ?MFC对COM的支持 ? 用MFC开发COM组件 ?ATL对COM的支持 ? 用ATL开发COM组件 ? 布置作业 Win32 SDK: Windows程序结构 ? 入口函数WinMain ? 应用初始化 ? 主窗口的创建及显示 ? 消息分发循环 ? 程序结束处理 Win32 SDK对COM的支持 ? Win32 SDK包括COM库函数的支持 Win32 SDK提供的一些头文件的说明 头文件 说明 Unknwn.h 标准接口IUnknown和IClassFactory的IID及接口成员函数的定义。 Wtypes.h 包含了COM使用的数据结构的说明。 Objidl.h 所有标准接口的定义,既可用于C语言风格的定义,也可用于C++语言风格 的定义。 Comdef.h 所有标准接口以及COM和OLE内部对象的CLSID。 ObjBase.h 所有的COM API函数的说明。 Ole2.h 所有经过封装的OLE辅助函数。 利用宏描 接口 DECLARE_INTERFACE_(IClassFactory, IUnknown) { STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR* ppvObj) 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提供的用于描 接口的宏 COM 接口有 的一些宏的说明 宏说明 DECLARE_INTERFACE(iface) 明接口iface, 的接口 。 DECLARE_INTERFACE_( iface, baseiface) 明接口iface, 接口baseiface 。 STDMETHOD(method) 明接口成员函数method,函数 HRESULT。 STDMETHOD_(type,method) 明接口成员函数method,函数 type。 MFC ? 应用 –AfxGetApp – CWinApp::InitInstance – CWinApp::ExitInstance – 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_DESTROY() 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应用:¢£?接MFC库的¥ DLL ?£?接 MFC库的¥ DLL MFC§currency1DLL ? '应用: – 支持OLE“???包容fi的SDI应用 – 支持OLE“???包容fi的MDI应用 – 支持fl?化(Automation)“?的SDI??MDI程序 – ActiveX 应用(OCX应用) MFC库结构 CObject CCmdTarget CWnd 应用 结构 窗口支持 – 文件“? 文? ??窗口 · ?? 对 ? ? ?”?…环‰ 支持 Windows 接? ?”对象 ` ODBC支持 DAO支持 ′? : Internet支持 fl?化 ?ˉ?˙对象支持 ¨` 结构 支持 ?? ? 用于′?的 数组 ? Internet MFC对COM应用的支持 用ˇ COM接口 class CDictionary { …… //构—函数和 构函数 HRESULT __stdcall QueryInterface(REFIID iid, void** ppvObj); ULONG __stdcall AddRef(); ULONG __stdcall 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_dictionaryObj; 用ˇ 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_spellCheckObj; private : struct DictWord *m_pData; char *m_DictFilename[128]; int m_Ref ; int m_nWordNumber, m_nStructNumber; }; 用ˇ COM接口( ) CDictionary::CDictionary() { ....... // Initializtion m_dictionaryObj. m_pParent = this; m_spellCheckObj. m_pParent = this; } 用ˇ COM接口( ) HRESULT CDictionary::QueryInterface(const IID& iid, void **ppvObj) { if (iid == IID_IUnknown || iid == IID_Dictionary) { *ppvObj = &m_dictionaryObj; AddRef(); return S_OK; } else if (iid == IID_SpellCheck) { *ppvObj = &m_spellCheckObj; AddRef(); return S_OK; } *ppv = NULL; return E_NOINTERFACE ; } 用ˇ COM接口( ) ULONG CDictionary::XDictionaryObj::QueryInterface(const IID& iid, void **ppvObj) { return m_pParent->QueryInterface(iid, ppvObj); } ULONG CDictionary::XDictionaryObj::AddRef() { return m_pParent->AddRef(); } ULONG CDictionary::XDictionaryObj::Release () { return m_pParent->Release (); } “用ˇ COM接口” 理 m_pData m_DictFilename[128] m_Ref m_nWordNumber m_nStructNumber QueryInterface AddRef Release ……. m_dictionaryObj m_spellCheckObj QueryInterface AddRef Release …… QueryInterface AddRef Release …… Vtable for IDictionary Vtable for ISpellCheck CDictionary vptr vptr CDictionary的 函数 MFC:接口 ? CCmdTarget ? CCmdTarget::m_dwRef 用 数 ? 接口 消息 ? 接口 : 了CCmdTarget 一?ˇ 的接 口ID以及接口vtable thisa 的 ?? ? offsetof宏:成员 的 ? DECLARE_INTERFACE_MAP #define DECLARE_INTERFACE_MAP() private: static const AFX_INTERFACEMAP_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_INTERFACEMAP { #ifdef _AFXDLL const AFX_INTERFACEMAP* (PASCAL pfnGetBaseMap)(); #else const AFX_INTERFACEMAP* pBaseMap; #endif const AFX_INTERFACEMAP_ENTRY* pEntry; }; 接口 定义 BEGIN_INTERFACE_MAP(CDictionary, CCmdTarget) INTERFACE_PART(CDictionary, IID_IDictionary, Dictionary) INTERFACE_PART(CDictionary, IID_ISpellCheck, SpellCheck) END_INTERFACE_MAP() 接口 的宏定义 #define BEGIN_INTERFACE_MAP(theClass, theBase) const AFX_INTERFACEMAP* PASCAL theClass::_GetBaseInterfaceMap() { return &theBase::interfaceMap; } const AFX_INTERFACEMAP* theClass::GetInterfaceMap() const { return &theClass::interfaceMap; } AFX_COMDAT const AFX_DATADEF AFX_INTERFACEMAP theClass::interfaceMap = { &theClass::_GetBaseInterfaceMap, &theClass::_interfaceEntries[0], }; AFX_COMDAT const AFX_DATADEF AFX_INTERFACEMAP_ENTRY theClass::_interfaceEntries[] = { #define INTERFACE_PART(theClass, iid, localClass) { &iid, offsetof(theClass, m_x##localClass) }, #define END_INTERFACE_MAP() { NULL, (size_t)-1 } }; MFC?o的? 对象 定义 class CDictionary : public CCmdTarget { DECLARE_DYNCREATE(CDictionary) CDictionary(); // protected constructor used by dynamic creation DECLARE_INTERFACE_MAP() ...... // IDictionary BEGIN_INTERFACE_PART(Dictionary, IDictionary) INIT_INTERFACE_PART(CDictionary, Dictionary) STDMETHOD_(BOOL, Initialize)(); …… STDMETHOD_(void, FreeLibrary)(); END_INTERFACE_PART_STATIC(Dictionary) // ISpellCheck BEGIN_INTERFACE_PART(SpellCheck, ISpellCheck) INIT_INTERFACE_PART(CDictionary, SpellCheck) STDMETHOD_(BOOL, CheckWord)(LPOLESTR, LPOLESTR *); END_INTERFACE_PART_STATIC(SpellCheck) }; MFC?o的? 对象 STDMETHODIMP_(ULONG) CDictionary::XDictionary::AddRef() { METHOD_PROLOGUE_EX_(CDictionary, Dictionary) return pThis->ExternalAddRef(); } ? METHOD_PROLOGUE_EX_宏定义: #define 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 aware long m_dwRef; LPUNKNOWN m_pOuterUnknown; // external controlling unknown if != NULL DWORD m_xInnerUnknown; // place-holder for inner controlling unknown public: // advanced operations void EnableAggregation(); // call to enable aggregation void ExternalDisconnect(); // forcibly disconnect LPUNKNOWN GetControllingUnknown(); // get controlling IUnknown for aggregate creation CCmdTarget IUnknown( ) public: // these versions do not delegate to m_pOuterUnknown DWORD InternalQueryInterface(const void*, LPVOID* ppvObj); DWORD InternalAddRef(); DWORD InternalRelease(); // these versions delegate to m_pOuterUnknown DWORD ExternalQueryInterface(const void*, LPVOID* ppvObj); DWORD ExternalAddRef(); DWORD ExternalRelease(); CCmdTarget QueryInterface DWORD CCmdTarget::InternalQueryInterface(const void* iid, LPVOID* ppvObj) { // check local interfaces if ((*ppvObj = GetInterface(iid)) != NULL) { // interface was found -- add a reference ExternalAddRef(); return S_OK; } // check aggregates if ((*ppvObj = QueryAggregates(iid)) != NULL) return S_OK; // interface ID not found, fail the call return (DWORD)E_NOINTERFACE; } CCmdTarget ExternalXXX成员 DWORD CCmdTarget::ExternalAddRef() { // delegate to controlling unknown if aggregated if (m_pOuterUnknown != NULL) return m_pOuterUnknown->AddRef(); return InternalAddRef(); } DWORD CCmdTarget::ExternalRelease() // …... // QueryInterface that is exported to normal clients DWORD CCmdTarget::ExternalQueryInterface(const void* iid, LPVOID* ppvObj) { // delegate to controlling unknown if aggregated if (m_pOuterUnknown != NULL) return m_pOuterUnknown->QueryInterface(*(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 “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 DllRegisterServer, 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_OLECREATE(...),定义?? #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 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,?了一些 o的 息, 包 括一? 。 ? DllGetClassObject- AfxDllGetClassObject- AfxGetModuleState进一?得到 ? 对象的构—函数和 构函数维护 用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 applications. 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, InsertWord)(LPOLESTR, LPOLESTR); STDMETHOD_(void, DeleteWord)( LPOLESTR); STDMETHOD_(BOOL, LookupWord)(LPOLESTR, LPOLESTR *); STDMETHOD_(BOOL, RestoreLibrary)(LPOLESTR); STDMETHOD_(void, FreeLibrary)(); END_INTERFACE_PART_STATIC(Dictionary) // ISpellCheck BEGIN_INTERFACE_PART(SpellCheck, ISpellCheck) INIT_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 "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() 支持 ? CDictionaryObj 明 入: 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) ATL介绍 ?ATL COM的 ′于MFC ? 使用多继承技术 多?接口 ? 支持多线程 ? QueryInterface用到了特殊的技术 ? 创建对象 ′于以往的技术 ? 优化 ATL概况 ? 封装了一些数据 –CComBSTR CComVariant CComPtr,等 ? COM接口和COM对象 – 接口 对象 ,等 ? 窗口的支持 – CWindow CWindowImpl CDialogImpl,等 ? 'COM特征的支持 – 永久?支持 – ?接点支持 – ??对象和枚举fi对象 – ActiveX control and container – 等 CComBSTR ? 封装了BSTR ? 提供了大?便利的?符串操作 – 构—函数 – 各种操作符以及一般的?符串操作 – 对于流(stream)的支持 ? 需 BSTR的地 ,都可以用CComBSTR来 代替 ? 注意owership CComVariant ? 封装了VARIANT ? ? 提供了 用的操作 – 构—函数 – 各种操作符以及一般的管理操作 – 对于流(stream)的支持 ? 需 VARIANT的地 ,都可以用 CComVARIANT来代替 CComPtr CComQIPtr ?Smart pointer template<class T> template<class T, const IID* piid = &__uuidof(T)> class CComPtr class CComQIPtr {{ public: public: T* p; T* p; ….. }; }; ? 优点: – fl?管理AddRef/Release – 大多数情况?,可以当作接口a 来使用 ? 注意:禁止调用“->Release”和“->AddRef” CComDispatchDriver ? 封装了IDispatch接口 ? ?了对接口a 的管理 外,有? 的功能: – ?访问函数: ? GetIDOfName/ GetProperty/ PutProperty ? GetPropertyByName/ PutPropertyByName – 法访问函数: ? by DISPID:Invoke0/Invoke1/Invoke2/InvokeN ?by Name:Invoke0/Invoke1/Invoke2/InvokeN – 两?¢£函数: ?By DISPID:GetProperty/PutProperty ATL的 层次 CMyClass CComObjectRootBase CComObjectRootEx<TM> IXxxImpl IMyItf1 IMyItf2 CComObject<T>等 CComXxxThreadModel CComObjectRootBase ? ObjectMain ? static InternalQueryInterface ? OuterAddRef/OuterRelease/OuterQueryInterface ? InternalFinalConstructAddRef/ InternalFinalConstructRelease ? '一些¢£函数 ? 联?: union { long m_dwRef; IUnknown* m_pOuterUnknown; }; ATL对象的线程 ? 用到了trait技术 ? 过编译?˙的 提供just thread-safe enough ? CComSingleThreadModel ? CComMultiThreadModel ? CComMultiThreadNoCS ? 提供了两?¢£成员函数和 ?typedef – Increment Decrement – AutoCriticalSection CriticalSection ThreadModelNoCS ATL对象 用 数 ? CComObjectRootEx – InternalAddRef – InternalRelease – 作用 匿名联?的m_dwRef成员上 ? CComObjectRootEx定义了一把锁 – 锁的 AutoCriticalSection – 对锁的封装ObjectLock,wrapper ? 用于 被聚?的情况? ATL对象 QueryInterface ? Table-driven QueryInterface ? Interface Map BEGIN_COM_MAP(class) COM_INTERFACE_ENTRY(itf) END_COM_MAP ? 一 struct _ATL_INTMAP_ENTRY { const IID* piid; DWORD dw; _ATL_CREATORARGFUNC *pFunc; }; ATL 的接口 ?IDispatchImpl ? IPersistStreamInitImpl ? IConnectionPointContainerImpl ? 举 : template<class T, const IID* piid, …> class IDispatchImpl : public T {…}; template <class T> class IConnectionPointContainerImpl : public IConnectionPointContainer{...}; class CMyObject : public IDispatchImpl<IMyDispInterface, &IID_IMyDispInterface,... >, public IConnectionPointContainerImpl< CMyObject > {…}; 真¥的ATL对象 ? 决定这?COM对象?何被分配,?否被聚?等 ? 区别: – 线程 ?以 ? 的,per-class,可以封装到 – 对象的 命周期和身份标识?以 ?对象 的,per-object, 延后到最终的 最初决定 ?CComObject : – template <class Base> CComObject : public Base {…}; – 支持聚?:class CComAggObject; – 支持聚?: class CComPolyObject; – template <class Base> CComObjectCached : public Base {…}; – template <class Base> CComObjectNoLock : public Base {…}; – template <class Base> CComObjectGlobal : public Base {…}; – template <class Base> CComObjectStack : public Base {…}; ATL对象的创建 ? 两??骤: – 使用CRT的构—fi – FinalConstruct ? 对应于FinalConstruct有FinalRelease ? 举 : CMyClassFactory::CreateInstance() { …… CComObject<CMyObject> *pObj = new CComObject<CMyObject>; …... pObj->InternalFinalConstructAddRef(); HRESULT hr = FinalConstruct(); pObj->InternalFinalConstructRelease(); …… } ATL Creators ? ?creator 有一?¢£CreateInstance函数: HRESULT WINAPI CreateInstance(void* pv, REFIID riid, LPVOID* ppv); ? 举 : template <class T> class CComCreator { public: static HRESULT WINAPI CreateInstance(void* pv, REFIID riid, LPVOID* ppv) { …… T *pObj = new T(pv); …... pObj->InternalFinalConstructAddRef(); HRESULT hr = FinalConstruct(); pObj->InternalFinalConstructRelease(); …… hr = p->QueryInterface(riid, ppv); …… } }; ATL Creators( ) ? '的creator 有 – CComCreator2 —— 根据pv参数?否 null 两?对象 择一 – CComFailCreator —— 假的创建 ? CMyObject 定义一? _CreatorClass, ? – typedef CComCreator<CComObject<CMyObject>> _CreatorClass; ?CComCoClass定义: template<class T, const CLSID* pclsid = &CLSID_NULL> class CComCoClass { public: …… template<class Q> static HRESULT CreateInstance(IUnknown* punkOuter, Q** pp) { return T::_CreatorClass::CreateInstance(punkOuter, __uuidof(Q), (void **)pp); } …… }; 聚?情况?对象结构? CMyClass CComObjectRootBase CComObjectRootEx<TM> IXxxImpl IMyItf1 IMyItf2 CComContainedObject CComXxxThreadModel CComAggObject IUnknown 委托IUnknown 委托IUnknown ATL 对象聚?的 template <class contained> class CComAggObject : public IUnknown, public CComObjectRootEx< contained::_ThreadModel::ThreadModelNoCS > { public : STDMETHOD_(ULONG, AddRef)() {…} STDMETHOD_(ULONG, Release)() {…} STDMETHOD(QueryInterface)(REFIID iid, void ** ppvObject){…} …… CComContainedObject<contained> m_contained; }; 委托IUnknown 委托IUnknown ATL 对象聚?的 ( ) template <class Base> //Base must be derived from CComObjectRoot class CComContainedObject : public Base { 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* 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) ATL Servers ? 功能 – Register and Unregister all class – exposing class object – managing server’s lifetime ?ATL 结构 – object map – CComModule Object Map ? 示 BEGIN_OBJECT_MAP(ObjectMap) OBJECT_ENTRY(CLSID_DictionaryObj, CDictionaryObj) OBJECT_ENTRY_NON_CREATEABLE(COtherObj) END_OBJECT_MAP() ? 宏定义: #define BEGIN_OBJECT_MAP(x) static _ATL_OBJMAP_ENTRY x[] = { #define END_OBJECT_MAP() {NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL}}; _ATL_OBJMAP_ENTRY定义 struct _ATL_OBJMAP_ENTRY { const CLSID* pclsid; HRESULT (WINAPI *pfnUpdateRegistry)(BOOL bRegister); _ATL_CREATORFUNC* pfnGetClassObject; _ATL_CREATORFUNC* pfnCreateInstance; IUnknown* pCF; DWORD dwRegister; _ATL_DESCRIPTIONFUNC* pfnGetObjectDescription; _ATL_CATMAPFUNC* pfnGetCategoryMap; void (WINAPI *pfnObjectMain)(bool bStarting); }; OBJECT_ENTRY定义 #define OBJECT_ENTRY(clsid, class) {&clsid, class::UpdateRegistry, class::_ClassFactoryCreatorClass::CreateInstance, class::_CreatorClass::CreateInstance, NULL, 0, class::GetObjectDescription, class::GetCategoryMap, class::ObjectMain }, #define OBJECT_ENTRY_NON_CREATEABLE(class) {&CLSID_NULL, class::UpdateRegistry, NULL, NULL, NULL, 0, NULL, class::GetCategoryMap, class::ObjectMain }, 的注 ? OBJECT_ENTRY 的class::UpdateRegistry – ? 都 提供UpdateRegistry成员 – 宏: ? DECLARE_NO_REGISTRY() ? DECLARE_REGISTRY(class, pid, vpid, nid, flags) ? DECLARE_REGISTRY_RESOURCE(x) ? DECLARE_REGISTRY_RESOURCEID(x) ? 成的工程使用 进ˉ注 – Registry Script File ? OBJECT_ENTRY宏包含: class::_ClassFactoryCreatorClass::CreateInstance ? DECLARE_CLASSFACTORY_EX宏定义: #define DECLARE_CLASSFACTORY_EX(cf) typedef CComCreator< CComObjectCached< cf > > _ClassFactoryCreatorClass; #define DECLARE_CLASSFACTORY() DECLARE_CLASSFACTORY_EX(CComClassFactory) ? CComCoClass定义 包含 DECLARE_CLASSFACTORY() 的创建 ? OBJECT_ENTRY宏包含: class::_CreatorClass::CreateInstance ? DECLARE_AGGREGATABLE(x)宏定义: #define DECLARE_AGGREGATABLE(x) public:typedef CComCreator2< CComCreator< CComObject< x > >, CComCreator< CComAggObject< x > > > _CreatorClass; ? CComCoClass定义 包含 DECLARE_AGGREGATABLE(T) 的?接 ? 的初始化 – in-proc server,DllGetClassObject – out-of-proc server,RegisterClassObject ? 把 创建函数 – CComClassFactory 有以?成员: _ATL_CREATORFUNC* m_pfnCreateInstance; ? 的CreateInstance 法调用 m_pfnCreateInstance CComModule ? ? – ATL inproc server:CComModule _Module; – ATL local server:CExeModule _Module; – service-base server:CServiceModule _Module; ? Init/Term函数 ? 注 功能 ? 提供 锁功能 编译优化 ? ATL_NO_VTABLE – 止 构—/ 构过程 调 vptr, 于 函数的 vtable 用 ?被构—/ 构函数访问,所以这 接fi优化 函数的vptr ? _ATL_MIN_CRT – 接标准C/C++?ˉ库 ? _ATL_DLL – ?£ 接atl.dll ? _ATL_STATIC_REGISTRY – ¢£ 接组件注 功能 ? 的ATL对象 class CDictionary : public CComObjectRootEx<CComSingleThreadModel>, public CComCoClass<CDictionary, &CLSID_Dictionary>, public IDictionary, public ISpellCheck { public: CDictionary() { } DECLARE_REGISTRY_RESOURCEID(IDR_DICTIONARY) DECLARE_PROTECT_FINAL_CONSTRUCT() BEGIN_COM_MAP(CDictionary) COM_INTERFACE_ENTRY(IDictionary) COM_INTERFACE_ENTRY(ISpellCheck) END_COM_MAP() ? 的ATL对象( ) public: // IDictionary STDMETHOD_(BOOL, Initialize)(); STDMETHOD_(BOOL, LoadLibrary)(LPOLESTR); STDMETHOD_(BOOL, InsertWord)(LPOLESTR, LPOLESTR); STDMETHOD_(void, DeleteWord)( LPOLESTR); STDMETHOD_(BOOL, LookupWord)(LPOLESTR, LPOLESTR *); STDMETHOD_(BOOL, RestoreLibrary)(LPOLESTR); STDMETHOD_(void, FreeLibrary)(); // ISpellCheck STDMETHOD_(BOOL, CheckWord)(LPOLESTR, LPOLESTR *); private: …… }; 过 ATL Object Wizard创建对象 过 ATL Object Wizard?置对象名? 过 ATL Object Wizard?置对象 ? 示和作业