COM学习笔记

来源:互联网 发布:淘宝如何申请延期收货 编辑:程序博客网 时间:2024/05/16 06:14
Function Show(ShowObj)If ShowObj.style.display = "" Then ShowObj.style.display = "none"Else ShowObj.style.display = ""End IfEnd Function'功能:显示/隐藏所有文字'用法:1、用 

COM 学习笔记

康  林 2004年11月

关键词:组件、接口、动态链接库、注册表、CLSID、GUID、IID、UUID

  1. 概念:

    1. 类型库:

    2. 组件:是一个接口的集合。

    3. 接口:是一个包含一个函数接针数组的内存结构。每一个数组元素包含的是一个由组件所实现的函数的地址。

      组件是接口的集合,接口是函数的集合。

  2. QueryInterface 的实现规则:

    1. QueryInterface 返回的总是同一个 IUnknown 指针。

    2. 若客户曾经获得过某个接口,那么它将总能获取此接口。

    3. 客户可以再次获得已经拥有的接口。

    4. 客户可以返回到起始接口。

    5. 若能够从某个接口获得某按按特定接口,那么可以从任意接口都将可以获得此接口。

  3. ProgID 与 CLSID的转换:

    1. ProgIDFromCLSID
      HRESULT CLSIDFromProgID(
        LPCOLESTR
      lpszProgID//Pointer to the ProgID
        LPCLSID pclsid         //Pointer to the CLSID
      );

    2. CLSIDFromProgID
      WINOLEAPI ProgIDFromCLSID(
        REFCLSID
      clsid//CLSID for which the ProgID is requested
        LPOLESTR * lplpszProgID
                         //Address of output variable that receives a
                         // pointer to the requested ProgID string
      );
       

  4. CLSID 与字符串的转换:

    1. CLSIDFromString
      HRESULT CLSIDFromString(
        LPOLESTR
      lpsz//Pointer to the string representation of the CLSID
        LPCLSID pclsid  //Pointer to the CLSID
      );

    2. StringFromCLSID
      WINOLEAPI StringFromCLSID(
        REFCLSID
      rclsid, //CLSID to be converted
        LPOLESTR * ppsz  //Address of output variable that receives a
                         // pointer to the resulting string
      );

    3. StringFromGUID2
      int StringFromGUID2(
        REFGUID
      rguid//Interface identifier to be converted
        LPOLESTR lpsz//Pointer to the resulting string on return
        int cchMax       //Character count of string at lpsz
      );
       

    4. StringFromIID
      WINOLEAPI StringFromIID(
        REFIID
      rclsid,     //Interface identifier to be converted
        LPOLESTR * lplpsz  //Address of output variable that receives a
                           // pointer to the resulting string
      );

    5. IIDFromString
      WINOLEAPI IIDFromString(
        LPOLESTR
      lpsz//Pointer to the string representation of the IID
        LPIID lpiid     //Pointer to the requested IID on return
      );

  5. 注册:

    1. 用程序注册:regsvr32.exe

    2. 调用动态函数库中的注册函数:DllRegisterServer

    3. 调用动态函数库中的反注册函数:DllUnregisterServer

  6. COM库函数:

    1. CoCreateInstance
        STDAPI CoCreateInstance(
           REFCLSID
      rclsid,     //Class identifier (CLSID) of the object
           LPUNKNOWN pUnkOuter, //Pointer to whether object is or isn't part
                                  // of an aggregate
           DWORD dwClsContext//Context for running executable code
           REFIID riid,         //Reference to the identifier of the interface
           LPVOID * ppv         //Address of output variable that receives
                                 // the interface pointer requested in riid
        );
      CoCreateInstance 实际上是调用
      CoGetClassObject 实现的。CoGetClassObject 将在注册表中查找指定的组件。找到之后,它将装载实现此组件的 DLL(用 CoLoadLibrary)。装载成功之后,它将调用在 DLL 服务器中的实现的 DllGetClassObject。此函数的作用是创建相应的类厂。另外 DllGetClassObject 还将查询 IClassFactory 接口,并将其返回给 CoCreateInstance。然后,CoCreatInstnce 将使用此接口来调用 IClassFactory::CreateInstance 函数。并查询指 CoCreateInstance 参数 riid 中指定的接口。在得到了此接口之后,CoCreateInstance 将释放相应的类厂并将此接口的指针返回给客户。然后客户就能使用此指针来调用组件中的某个方法了。

    2. CoGetClassObject
      STDAPI CoGetClassObject(
        REFCLSID
      rclsid//CLSID associated with the class object
        DWORD dwClsContext,
                          //Context for running executable code
        COSERVERINFO * pServerInfo,
                          //Pointer to machine on which the object is to
                          // be instantiated
        REFIID riid,      //Reference to the identifier of the interface
        LPVOID * ppv      //Address of output variable that receives the
                          // interface pointer requested in riid
      );

    3. CoFreeUnusedLibraries:释放不再使用的DLL
       
  7. 包容与聚合:
  8. 接口指针类(智能接口指针):

    1. ATL中有 CComPrt 和 CComQIprt(#include <ATLBASE.H>)

      template <class T>class CComPtr{public:typedef T _PtrClass;CComPtr(){p=NULL;}CComPtr(T* lp){if ((p = lp) != NULL)p->AddRef();}CComPtr(const CComPtr<T>& lp){if ((p = lp.p) != NULL)p->AddRef();}~CComPtr(){if (p)p->Release();}void Release(){IUnknown* pTemp = p;if (pTemp){p = NULL;pTemp->Release();}}operator T*() const{return (T*)p;}T& operator*() const{ATLASSERT(p!=NULL);return *p;}//The assert on operator& usually indicates a bug.  If this is really//what is needed, however, take the address of the p member explicitly.T** operator&(){ATLASSERT(p==NULL);return &p;}_NoAddRefReleaseOnCComPtr<T>* operator->() const{ATLASSERT(p!=NULL);return (_NoAddRefReleaseOnCComPtr<T>*)p;}T* operator=(T* lp){return (T*)AtlComPtrAssign((IUnknown**)&p, lp);}T* operator=(const CComPtr<T>& lp){return (T*)AtlComPtrAssign((IUnknown**)&p, lp.p);}bool operator!() const{return (p == NULL);}bool operator<(T* pT) const{return p < pT;}bool operator==(T* pT) const{return p == pT;}// Compare two objects for equivalencebool IsEqualObject(IUnknown* pOther){if (p == NULL && pOther == NULL)return true; // They are both NULL objects
      if (p == NULL || pOther == NULL)return false; // One is NULL the other is not
      CComPtr<IUnknown> punk1;CComPtr<IUnknown> punk2;p->QueryInterface(IID_IUnknown, (void**)&punk1);pOther->QueryInterface(IID_IUnknown, (void**)&punk2);return punk1 == punk2;}void Attach(T* p2){if (p)p->Release();p = p2;}T* Detach(){T* pt = p;p = NULL;return pt;}HRESULT CopyTo(T** ppT){ATLASSERT(ppT != NULL);if (ppT == NULL)return E_POINTER;*ppT = p;if (p)p->AddRef();return S_OK;}HRESULT SetSite(IUnknown* punkParent){return AtlSetChildSite(p, punkParent);}HRESULT Advise(IUnknown* pUnk, const IID& iid, LPDWORD pdw){return AtlAdvise(p, pUnk, iid, pdw);}HRESULT CoCreateInstance(REFCLSID rclsid, LPUNKNOWN pUnkOuter = NULL, DWORD dwClsContext = CLSCTX_ALL){ATLASSERT(p == NULL);return ::CoCreateInstance(rclsid, pUnkOuter, dwClsContext, __uuidof(T), (void**)&p);}HRESULT CoCreateInstance(LPCOLESTR szProgID, LPUNKNOWN pUnkOuter = NULL, DWORD dwClsContext = CLSCTX_ALL){CLSID clsid;HRESULT hr = CLSIDFromProgID(szProgID, &clsid);ATLASSERT(p == NULL);if (SUCCEEDED(hr))hr = ::CoCreateInstance(clsid, pUnkOuter, dwClsContext, __uuidof(T), (void**)&p);return hr;}template <class Q>HRESULT QueryInterface(Q** pp) const{ATLASSERT(pp != NULL && *pp == NULL);return p->QueryInterface(__uuidof(Q), (void**)pp);}T* p;};
      template <class T, const IID* piid = &__uuidof(T)>class CComQIPtr{public:typedef T _PtrClass;CComQIPtr(){p=NULL;}CComQIPtr(T* lp){if ((p = lp) != NULL)p->AddRef();}CComQIPtr(const CComQIPtr<T,piid>& lp){if ((p = lp.p) != NULL)p->AddRef();}CComQIPtr(IUnknown* lp){p=NULL;if (lp != NULL)lp->QueryInterface(*piid, (void **)&p);}~CComQIPtr(){if (p)p->Release();}void Release(){IUnknown* pTemp = p;if (pTemp){p = NULL;pTemp->Release();}}operator T*() const{return p;}T& operator*() const{ATLASSERT(p!=NULL); return *p;}//The assert on operator& usually indicates a bug.  If this is really//what is needed, however, take the address of the p member explicitly.T** operator&(){ATLASSERT(p==NULL);return &p;}_NoAddRefReleaseOnCComPtr<T>* operator->() const{ATLASSERT(p!=NULL);return (_NoAddRefReleaseOnCComPtr<T>*)p;}T* operator=(T* lp){return (T*)AtlComPtrAssign((IUnknown**)&p, lp);}T* operator=(const CComQIPtr<T,piid>& lp){return (T*)AtlComPtrAssign((IUnknown**)&p, lp.p);}T* operator=(IUnknown* lp){return (T*)AtlComQIPtrAssign((IUnknown**)&p, lp, *piid);}bool operator!() const{return (p == NULL);}bool operator<(T* pT) const{return p < pT;}bool operator==(T* pT) const{return p == pT;}// Compare two objects for equivalencebool IsEqualObject(IUnknown* pOther){if (p == NULL && pOther == NULL)return true; // They are both NULL objects
      if (p == NULL || pOther == NULL)return false; // One is NULL the other is not
      CComPtr<IUnknown> punk1;CComPtr<IUnknown> punk2;p->QueryInterface(IID_IUnknown, (void**)&punk1);pOther->QueryInterface(IID_IUnknown, (void**)&punk2);return punk1 == punk2;}void Attach(T* p2){if (p)p->Release();p = p2;}T* Detach(){T* pt = p;p = NULL;return pt;}HRESULT CopyTo(T** ppT){ATLASSERT(ppT != NULL);if (ppT == NULL)return E_POINTER;*ppT = p;if (p)p->AddRef();return S_OK;}HRESULT SetSite(IUnknown* punkParent){return AtlSetChildSite(p, punkParent);}HRESULT Advise(IUnknown* pUnk, const IID& iid, LPDWORD pdw){return AtlAdvise(p, pUnk, iid, pdw);}HRESULT CoCreateInstance(REFCLSID rclsid, LPUNKNOWN pUnkOuter = NULL, DWORD dwClsContext = CLSCTX_ALL){ATLASSERT(p == NULL);return ::CoCreateInstance(rclsid, pUnkOuter, dwClsContext, __uuidof(T), (void**)&p);}HRESULT CoCreateInstance(LPCOLESTR szProgID, LPUNKNOWN pUnkOuter = NULL, DWORD dwClsContext = CLSCTX_ALL){CLSID clsid;HRESULT hr = CLSIDFromProgID(szProgID, &clsid);ATLASSERT(p == NULL);if (SUCCEEDED(hr))hr = ::CoCreateInstance(clsid, pUnkOuter, dwClsContext, __uuidof(T), (void**)&p);return hr;}template <class Q>HRESULT QueryInterface(Q** pp){ATLASSERT(pp != NULL && *pp == NULL);return p->QueryInterface(__uuidof(Q), (void**)pp);}T* p;};
      //Specialization to make it worktemplate<>class CComQIPtr<IUnknown, &IID_IUnknown>{public:typedef IUnknown _PtrClass;CComQIPtr(){p=NULL;}CComQIPtr(IUnknown* lp){//Actually do a QI to get identityp=NULL;if (lp != NULL)lp->QueryInterface(IID_IUnknown, (void **)&p);}CComQIPtr(const CComQIPtr<IUnknown,&IID_IUnknown>& lp){if ((p = lp.p) != NULL)p->AddRef();}~CComQIPtr(){if (p)p->Release();}void Release(){IUnknown* pTemp = p;if (pTemp){p = NULL;pTemp->Release();}}operator IUnknown*() const{return p;}IUnknown& operator*() const{ATLASSERT(p!=NULL);return *p;}//The assert on operator& usually indicates a bug.  If this is really//what is needed, however, take the address of the p member explicitly.IUnknown** operator&(){ATLASSERT(p==NULL);return &p;}_NoAddRefReleaseOnCComPtr<T>* operator->() const{ATLASSERT(p!=NULL);return (_NoAddRefReleaseOnCComPtr<T>*)p;}IUnknown* operator=(IUnknown* lp){//Actually do a QI to get identityreturn (IUnknown*)AtlComQIPtrAssign((IUnknown**)&p, lp, IID_IUnknown);}IUnknown* operator=(const CComQIPtr<IUnknown,&IID_IUnknown>& lp){return (IUnknown*)AtlComPtrAssign((IUnknown**)&p, lp.p);}bool operator!() const{return (p == NULL);}bool operator<(IUnknown* pT) const{return p < pT;}bool operator==(IUnknown* pT) const{return p == pT;}// Compare two objects for equivalencebool IsEqualObject(IUnknown* pOther){if (p == NULL && pOther == NULL)return true; // They are both NULL objects
      if (p == NULL || pOther == NULL)return false; // One is NULL the other is not
      CComPtr<IUnknown> punk1;CComPtr<IUnknown> punk2;p->QueryInterface(IID_IUnknown, (void**)&punk1);pOther->QueryInterface(IID_IUnknown, (void**)&punk2);return punk1 == punk2;}IUnknown* Detach(){IUnknown* pt = p;p = NULL;return pt;}HRESULT CopyTo(T** ppT){ATLASSERT(ppT != NULL);if (ppT == NULL)return E_POINTER;*ppT = p;if (p)p->AddRef();return S_OK;}HRESULT SetSite(IUnknown* punkParent){return AtlSetChildSite(p, punkParent);}HRESULT Advise(IUnknown* pUnk, const IID& iid, LPDWORD pdw){return AtlAdvise(p, pUnk, iid, pdw);}HRESULT CoCreateInstance(REFCLSID rclsid, LPUNKNOWN pUnkOuter = NULL, DWORD dwClsContext = CLSCTX_ALL){ATLASSERT(p == NULL);return ::CoCreateInstance(rclsid, pUnkOuter, dwClsContext, __uuidof(T), (void**)&p);}HRESULT CoCreateInstance(LPCOLESTR szProgID, LPUNKNOWN pUnkOuter = NULL, DWORD dwClsContext = CLSCTX_ALL){CLSID clsid;HRESULT hr = CLSIDFromProgID(szProgID, &clsid);ATLASSERT(p == NULL);if (SUCCEEDED(hr))hr = ::CoCreateInstance(clsid, pUnkOuter, dwClsContext, __uuidof(T), (void**)&p);return hr;}template <class Q>HRESULT QueryInterface(Q** pp){ATLASSERT(pp != NULL && *pp == NULL);return p->QueryInterface(__uuidof(Q), (void**)pp);}IUnknown* p;};
      #define com_cast CComQIPtr

    2. MFC中有CIP(#include <afxcom_.h>)

      // This is a part of the Microsoft Foundation Classes C++ library.// Copyright (C) 1992-1998 Microsoft Corporation// All rights reserved.//// This source code is only intended as a supplement to the// Microsoft Foundation Classes Reference and related// electronic documentation provided with the library.// See these sources for detailed information regarding the// Microsoft Foundation Classes product.
      /////////////////////////////////////////////////////////////////////////////// AFXCOM_.H//// THIS FILE IS FOR MFC IMPLEMENTATION ONLY.
      #ifndef __AFXCOM_H__#define __AFXCOM_H__
      #ifndef _OBJBASE_H_#include <objbase.h>#endif
      /////////////////////////////////////////////////////////////////////////////
      #ifdef _AFX_MINREBUILD#pragma component(minrebuild, off)#endif#ifndef _AFX_FULLTYPEINFO#pragma component(mintypeinfo, on)#endif
      /////////////////////////////////////////////////////////////////////////////
      #ifndef _AFX_NOFORCE_LIBS#pragma comment(lib, "uuid.lib")#endif
      /////////////////////////////////////////////////////////////////////////////
      #ifdef _AFX_PACKING#pragma pack(push, _AFX_PACKING)#endif
      #ifndef ASSERT#ifndef _INC_CRTDBG#include <crtdbg.h>#endif // _INC_CRTDBG#define ASSERT(x) _ASSERT(x)#endif // ASSERT
      /////////////////////////////////////////////////////////////////////////////
      template<class _Interface, const IID* _IID>class _CIP{public:// Declare interface type so that the type may be available outside// the scope of this template.typedef _Interface Interface;
      // When the compiler supports references in template params,// _CLSID will be changed to a reference.  To avoid conversion// difficulties this function should be used to obtain the// CLSID.static const IID& GetIID(){ ASSERT(_IID != NULL); return *_IID; }
      // Construct empty in preperation for assignment._CIP();
      // Copy the pointer and AddRef()._CIP(const _CIP& cp) : _pInterface(cp._pInterface){ _AddRef(); }
      // Saves and AddRef()'s the interface_CIP(Interface* pInterface) : _pInterface(pInterface){ _AddRef(); }
      // Copies the pointer.  If bAddRef is TRUE, the interface will// be AddRef()ed._CIP(Interface* pInterface, BOOL bAddRef): _pInterface(pInterface){if (bAddRef){ASSERT(pInterface != NULL);_AddRef();}}
      // Calls CoCreateClass with the provided CLSID._CIP(const CLSID& clsid, DWORD dwClsContext = CLSCTX_INPROC_SERVER): _pInterface(NULL){CreateObject(clsid, dwClsContext);}
      // Calls CoCreateClass with the provided CLSID retrieved from// the string._CIP(LPOLESTR str, DWORD dwClsContext = CLSCTX_INPROC_SERVER): _pInterface(NULL){CreateObject(str, dwClsContext);}
      // Saves and AddRef()s the interface._CIP& operator=(Interface* pInterface){if (_pInterface != pInterface){Interface* pOldInterface = _pInterface;_pInterface = pInterface;_AddRef();if (pOldInterface != NULL)pOldInterface->Release();}return *this;}
      // Copies and AddRef()'s the interface._CIP& operator=(const _CIP& cp){ return operator=(cp._pInterface); }
      // Releases any current interface and loads the class with the// provided CLSID._CIP& operator=(const CLSID& clsid){CreateObject(clsid);return *this;}
      // Calls CoCreateClass with the provided CLSID retrieved from// the string._CIP& operator=(LPOLESTR str){CreateObject(str);return *this;}
      ~_CIP();
      // Saves/sets the interface without AddRef()ing.  This call// will release any previously aquired interface.void Attach(Interface* pInterface){_Release();_pInterface = pInterface;}
      // Saves/sets the interface only AddRef()ing if bAddRef is TRUE.// This call will release any previously aquired interface.void Attach(Interface* pInterface, BOOL bAddRef){_Release();_pInterface = pInterface;if (bAddRef){ASSERT(pInterface != NULL);pInterface->AddRef();}}
      // Simply NULL the interface pointer so that it isn't Released()'ed.void Detach(){ASSERT(_pInterface);_pInterface = NULL;}
      // Return the interface.  This value may be NULLoperator Interface*() const{ return _pInterface; }
      // Queries for the unknown and return itoperator IUnknown*(){ return _pInterface; }
      // Provides minimal level assertion before use.operator Interface&() const{ ASSERT(_pInterface); return *_pInterface; }
      // Allows an instance of this class to act as though it were the// actual interface.  Also provides minimal assertion verification.Interface& operator*() const{ ASSERT(_pInterface); return *_pInterface; }
      // Returns the address of the interface pointer contained in this// class.  This is useful when using the COM/OLE interfaces to create// this interface.Interface** operator&(){_Release();_pInterface = NULL;return &_pInterface;}
      // Allows this class to be used as the interface itself.// Also provides simple assertion verification.Interface* operator->() const{ ASSERT(_pInterface != NULL); return _pInterface; }
      // This operator is provided so that simple boolean expressions will// work.  For example: "if (p) ...".// Returns TRUE if the pointer is not NULL.operator BOOL() const{ return _pInterface != NULL; }
      // Returns TRUE if the interface is NULL.// This operator will be removed when support for type bool// is added to the compiler.BOOL operator!(){ return _pInterface == NULL; }
      // Provides assertion verified, Release()ing of this interface.void Release(){ASSERT(_pInterface != NULL);_pInterface->Release();_pInterface = NULL;}
      // Provides assertion verified AddRef()ing of this interface.void AddRef(){ ASSERT(_pInterface != NULL); _pInterface->AddRef(); }
      // Another way to get the interface pointer without casting.Interface* GetInterfacePtr() const{ return _pInterface; }
      // Loads an interface for the provided CLSID.// Returns an HRESULT.  Any previous interface is released.HRESULT CreateObject(const CLSID& clsid, DWORD dwClsContext = CLSCTX_INPROC_SERVER){_Release();HRESULT hr = CoCreateInstance(clsid, NULL, dwClsContext,GetIID(), reinterpret_cast<void**>(&_pInterface));ASSERT(SUCCEEDED(hr));return hr;}
      // Creates the class specified by clsidString.  clsidString may// contain a class id, or a prog id string.HRESULT CreateObject(LPOLESTR clsidString, DWORD dwClsContext=CLSCTX_INPROC_SERVER){ASSERT(clsidString != NULL);CLSID clsid;HRESULT hr;if (clsidString[0] == '{')hr = CLSIDFromString(clsidString, &clsid);elsehr = CLSIDFromProgID(clsidString, &clsid);ASSERT(SUCCEEDED(hr));if (FAILED(hr))return hr;return CreateObject(clsid, dwClsContext);}
      // Performs a QI on pUnknown for the interface type returned// for this class.  The interface is stored.  If pUnknown is// NULL, or the QI fails, E_NOINTERFACE is returned and// _pInterface is set to NULL.HRESULT QueryInterface(IUnknown* pUnknown){if (pUnknown == NULL) // Can't QI NULL{operator=(static_cast<Interface*>(NULL));return E_NOINTERFACE;}
      // Query for this interfaceInterface* pInterface;HRESULT hr = pUnknown->QueryInterface(GetIID(),reinterpret_cast<void**>(&pInterface));if (FAILED(hr)){// If failed intialize interface to NULL and return HRESULT.Attach(NULL);return hr;}
      // Save the interface without AddRef()ing.Attach(pInterface);return hr;}
      private:// Releases only if the interface is not null.// The interface is not set to NULL.void _Release(){if (_pInterface != NULL)_pInterface->Release();}
      // AddRefs only if the interface is not NULLvoid _AddRef(){if (_pInterface != NULL)_pInterface->AddRef();}
      // The Interface.Interface* _pInterface;}; // class _CIP
      template<class _Interface, const IID* _IID>_CIP<_Interface, _IID>::_CIP<_Interface, _IID>(): _pInterface(NULL){}
      template<class _Interface, const IID* _IID>_CIP<_Interface, _IID>::~_CIP<_Interface, _IID>(){// If we still have an interface then Release() it.  The interface// may be NULL if Detach() has previosly been called, or if it was// never set.
      _Release();}
      template<class _Interface, const IID* _IID>class CIP : public _CIP<_Interface, _IID>{public:// Simplified name for base class and provide derived classes// access to base typetypedef _CIP<_Interface, _IID> BC;
      // Provideds derived classes access to the interface type.typedef _Interface Interface;
      // Construct empty in preperation for assignment.CIP() { }~CIP();
      // Copy the pointer and AddRef().CIP(const CIP& cp) : _CIP<_Interface, _IID>(cp) { }
      // Saves and AddRef()s the interface.CIP(Interface* pInterface) : _CIP<_Interface, _IID>(pInterface) { }
      // Saves the interface and AddRef()s only if bAddRef is TRUE.CIP(Interface* pInterface, BOOL bAddRef): _CIP<_Interface, _IID>(pInterface, bAddRef) { }
      // Queries for this interface.CIP(IUnknown* pUnknown){if (pUnknown == NULL)return;Interface* pInterface;HRESULT hr = pUnknown->QueryInterface(GetIID(),reinterpret_cast<void**>(&pInterface));ASSERT(SUCCEEDED(hr));Attach(pInterface);}
      // Creates the interface from the CLSID.CIP(const CLSID& clsid) : _CIP<_Interface, _IID>(clsid) { }
      // Creates the interface from the CLSID.CIP(LPOLESTR str) : _CIP<_Interface, _IID>(str) { }
      // Copies and AddRef()'s the interface.CIP& operator=(const CIP& cp){ _CIP<_Interface, _IID>::operator=(cp); return *this; }
      // Saves and AddRef()s the interface.CIP& operator=(Interface* pInterface){ _CIP<_Interface, _IID>::operator=(pInterface); return *this; }
      CIP& operator=(IUnknown* pUnknown){HRESULT hr = QueryInterface(pUnknown);ASSERT(SUCCEEDED(hr));return *this;}
      // Releases any current interface and loads the class with the// provided CLSID.CIP& operator=(const CLSID& clsid){ _CIP<_Interface, _IID>::operator=(clsid); return *this; }
      // Releases any current interface and loads the class with the// provided CLSID.CIP& operator=(LPOLESTR str){ _CIP<_Interface, _IID>::operator=(str); return *this; }}; // class CIP
      template<class _Interface, const IID* _IID>CIP<_Interface, _IID>::~CIP(){}
      #if _MSC_VER > 1020template<>#endifclass CIP<IUnknown, &IID_IUnknown> : public _CIP<IUnknown, &IID_IUnknown>{public:// Simplified name for base class and provide derived classes// access to base typetypedef _CIP<IUnknown, &IID_IUnknown> BC;
      // Provideds derived classes access to the interface type.typedef IUnknown Interface;
      // Construct empty in preperation for assignment.CIP() { }
      // Copy the pointer and AddRef().CIP(const CIP& cp) : _CIP<IUnknown, &IID_IUnknown>(cp) { }
      // Saves and AddRef()s the interface.CIP(Interface* pInterface): _CIP<IUnknown, &IID_IUnknown>(pInterface) { }
      // Saves and then AddRef()s only if bAddRef is TRUE.CIP(Interface* pInterface, BOOL bAddRef): _CIP<IUnknown, &IID_IUnknown>(pInterface, bAddRef) { }
      // Creates the interface from the CLSID.CIP(const CLSID& clsid) : _CIP<IUnknown, &IID_IUnknown>(clsid) { }
      // Creates the interface from the CLSID.CIP(LPOLESTR str) : _CIP<IUnknown, &IID_IUnknown>(str) { }
      // Copies and AddRef()'s the interface.CIP& operator=(const CIP& cp){ _CIP<IUnknown, &IID_IUnknown>::operator=(cp); return *this; }
      // Saves and AddRef()s the interface.  The previously saved// interface is released.CIP& operator=(Interface* pInterface){ _CIP<IUnknown, &IID_IUnknown>::operator=(pInterface); return *this; }
      // Releases any current interface and loads the class with the// provided CLSID.CIP& operator=(const CLSID& clsid){ _CIP<IUnknown, &IID_IUnknown>::operator=(clsid); return *this; }
      // Releases any current interface and loads the class with the// provided CLSID.CIP& operator=(LPOLESTR str){ _CIP<IUnknown, &IID_IUnknown>::operator=(str); return *this; }
      // Queries for the unknown and return itoperator IUnknown*(){ return GetInterfacePtr(); }
      // Verifies that pUnknown is not null and performs assignment.HRESULT QueryInterface(IUnknown* pUnknown){_CIP<IUnknown, &IID_IUnknown>::operator=(pUnknown);return pUnknown != NULL ? S_OK : E_NOINTERFACE;}};  // CIP<IUnknown, &IID_IUnknown>
      #define IPTR(x) CIP<x, &IID_##x>#define DEFINE_IPTR(x) typedef IPTR(x) x##Ptr;
      /////////////////////////////////////////////////////////////////////////////
      #ifdef _AFX_PACKING#pragma pack(pop)#endif
      #ifdef _AFX_MINREBUILD#pragma component(minrebuild, on)#endif#ifndef _AFX_FULLTYPEINFO#pragma component(mintypeinfo, off)#endif
      #endif // __AFXCOM_H__
      /////////////////////////////////////////////////////////////////////////////

    3. 使用接口类的成员函数,用 . 操作符。例如:
      CComQIPtr <InterfaceClass, &IID> spIF;
      spIF.Release(); //释放接口指针
    4. 释放接口指针类(智能接口指针):
      CComQIPtr <InterfaceClass, &IID> spIF;
      spIF = NULL; //释放接口指针
  9. C++包装类:(MFC OLE)

用嵌套类实现接口:

用 ATL 实现接口

  • 增加 ATL 对象类
    1. 操作步骤
    2. 增加的内容
     
  • 添加接口函数
    1. 操作步骤


      图五、调出增加接口方法的菜单


      图六、增加接口函数 Add


      图七、增加接口函数 Cat

        请严格按照图六的方式,增加Add()函数;由于图七中增加Cat()函数的参数比较长,我没有适当的输入空格,请大家自己输入的时候注意一下。[in]表示参数方向是输入;[out]表示参数方向是输出;[out,retval]表示参数方向是输出,同时可以作为函数运算结果的返回值。一个函数中,可以有多个[in]、[out],但[retval]只能有一个,并且要和[out]组合后在最后一个位置。(注5)

      图八、接口函数定义完成后的图示
        我们都知道,要想改变 C++ 中的类函数,需要修改两个地方:一是头文件(.h)中类的函数声明,二是函数体(.cpp)文件的实现处。而我们现在用 ATL 写组件程序,则还要修改一个地方,就是接口定义(IDL)文件。别着急 IDL 下次就要讨论啦。
        由于 vc6.0 的BUG,导致大家在增加完接口和接口函数后,可能不会向上图(图八)所表现的样式。解决方法:
        1 关闭工程,然后重新打开 该方法常常有效 2 关闭 IDE,然后重新运行   3 打开 IDL 文件,检查接口函数是否正确,如不正确请修改   4 打开 IDL 文件,随便修改一下(加一个空格,再删除这个空格),然后保存 该方法常常有效 5 打开 h/cpp 文件,检查函数是否存在或是否正确,有则改之 无则嘉勉,不说完这个成语心理别扭 6 删除 IDL/H/CPP 中的接口函数,然后 再来一遍 7 重新建立工程、重新安装vc、重新安装windows、砸计算机 砸!


       

    2. 增加内容
       

    其它文章索引

    1. 字符串的处理,见 VC知识库第九期 《COM编程入门——第一部分》
    2. 用ATL建立轻量级的COM对,见 VC 知识库第十三期
  • 原创粉丝点击