CComPtr和CComQIPtr是智能接口指针类,它们在销毁的时候,不需要手动去释放接口指针,在赋值的时候,也不需要手动的AddRef,在出现异常的时候,会自动处理异常,而不需要额外的异常处理代码。 CComPtr和CComQIPtr的不同的地方:CComPtr只能创建固定的特定的接口指针实例。而CComQIPtr不但实现了CComPtr的所有的功能,而且当我们把一个不同类型的接口指针赋值给CComQIPtr的时候,CComQIPtr会自动的调用接口指针的QueryInterface接口,来获得对应的正确的接口指针。 (1) 构造函数 第一个参数为智能接口指针的类型,第二个参数为 智能指针的接口ID。 CComPtr<IUnknown> punk; //下面三个例子完全相同 CComPtr<IXXX> pno; CComPtr<IXXX,&__uuidof(IXXX)> pno; CComPtr<IXXX,&IID_IXXX> pno; CComQIPtr可以用任何一个类型的接口指针初始化,如果初始化的值与CComQIPtr的类型相同,那么构造函数简单调用 指针的AddRef,但是,如果类型不同的话,它会先调用指针的QueryInterface来获得相同的类型的接口指针,当QueryInterface失败的话,内部指针会被设置为NULL。 所有下面的代码,可以用来检测是否转换成功: [cpp] view plaincopy
(2)赋值 赋值的时候,发生下面三件事: 111. 如果当前指针不为空,那么释放当前指针 222. 如果源指针不为空,那么AddRef 333. 将当前指针设置为源指针 oprator = 可以让我们把任何一个CComPtr赋值给CComQIPtr对象,如果有必要就会调用QueryInterface . 例如: [cpp] view plaincopy
(3) CoCreateInstance方法 CComPtr提供了一个实例化对象的方法 HRESULT CoCreateInstance(REFCLSID rclsid,LPUNKNOWN pUnkOuter=NULL, DWORD dwClsCOntext=CLSCTX_ALL); HRESULT CoCreateInstance(LPCOLESTR szProgID, LPUNKNOSWN pUnkOuter=NULL, DWORD dwClsContxt=CLSCTX_ALL); 后两个参数不管,第一个参数要不传入CLSID,要不传入字符串形式的progID. 例子代码如下: [cpp] view plaincopy
(4) operator *() 当对CComPtr解除指针的引用时,跟普通的指针一样,返回一个内部指针类型的引用。 (5) operator &() 获取智能指针对象的地址,实际上也是返回内部指针的地址,跟普通指针一样。 (6) 在调用ComUninitialize方法前,需要手动释放所有的全局或者静态变量。 如何手动释放呢: 111.设置指针指向NULL 222.调用Release方法,注意是要调用智能指针的Release方法,而不是内部指针的,指针指针的Release方法,会调用内部指针的Relase,然后设置内部指针为NULL,这样就可以防止多次释放接口。 (7)CopyTo方法,拷贝后的智能指针生命周期完全独立。 我们用CopyTo方法,将指针拷贝到一个out型参数。 (8)Detach 和Attach方法 在返回一个我们不再需要的接口指针给调用者的时候,我们可以用Deatch方法。 当我们需要把原始指针的所有权转移到智能指针时候,用Attach方法。 (9) QueryInterface方法 他只需要传入期望获得的接口类型的变量地址,即可。 CComPtr<IFoo> pFoo=...; CComPtr<IBar> pBar; HRESULT hr= pFoo.QueryInterface(&pBar); (10) IsEqualObject方法 IsEqualObject方法用来判断两个接口指针释放引用的是同一个对象。 (11) != 和 == 操作符 跟普通的 一样 (12) CComPtr对IDispatch的特化 CComPtr<IDispatch> iptr; 属性调用的辅助函数 111. GetIDOfName(LPCOLESTR lpsz,DISPID * pdispid) 这个方法,获得属性的DISPID 222.GetProPerty(DISPID dwDispid, VARIANT * pVar) 这个方法,获得属性。 SetProPerty(DISPID dwDispid, VARIANT * pVar) 这个方法,设置属性。 333. GetPropertyByName(LPCOLESTR lpsz, VARIANT * pVar) SetPropertyByName(LPCOLESTR lpsz, VARIANT * pVar) 直接通过名称,获得和设置属性。 方法调用的辅助函数: 111. HRESULT Invoke0(DISPID dispid,VARIANT * pvarRet=NULL); 通过DISPID调用 没有参数的方法。 HRESULT Invoke0(LPCOLESTR lpszName, VARIANT * pvarRet=NULL); 通过方法名称,调用没有参数的方法。 HRESULT Invoke1(DISPID dispid,VARIANT * param1, VARIANT * pvarRet=NULL); 通过DISPID调用 有一个参数的方法。 HRESULT Invoke1(LPCLOESTR lpszName ,VARIANT * param1, VARIANT * pvarRet=NULL); 通过方法名称,调用有一个参数的方法。 HRESULT InvokeN(DISPID dispid,VARIANT* params, int nParams, VARIANT * pvarRet=NULL); 通过DISPID调用有N个参数的方法。 HRESULT InvokeN(LPCLOESTR lpszName ,VARIANT * params,int nParams, VARIANT * pvarRet=NULL); 通过方法名称调用有N个参数的方法。 注意,通过参数列表的方法调用的时候,参数是反向的顺序,最后一个参数是元素0。 切记。 原文:http://blog.csdn.net/tangaowen/article/details/6554753 |
|