六、COM_INTERFACE_ENTRY_AGGREGATE_BLIND 参ATL例程COMMAP
上一节我们讲了COM_INTERFACE_ENTRY_AGGREGATE,这节要介绍的宏与它很类似。
从定义上就可以看出,它与上一节介绍宏的唯一区别就在于,它没有指明接口ID!!
所以在它的定义中第一项也是NULL。
这个宏的用法与我们COM_INTERFACE_ENTRY_AGGREGATE一模一样。大家可以参考上一节内容以及ATL的例程COMMAP。
我们来看看AtlInternalQueryInterface()中的相关代码。
若没指定接口ID,也继续执行后面的操作,可见即使并非我们所需要的IID,也会执行_Delegate.
从上可见,这个宏适用于一个聚集组件有多个接口的情况,这样只要是查询这个聚集组件的接口,就会进入_Delegate函数。但要特别注意的是这个宏的位置!! 比如若是这样的顺序:
先看看它的典型用法:
与一般的组件并无二样。
与宏COM_INTERFACE_ENTRY_AGGREGRATE(_)不同,COuter不用在FinalConstruct中创建聚集组件。外部组件会自动创建聚集组件!!!
1。
2。
3。
因为_Cache,_CComCacheData,CComAggregateCreator这几个类和函数我们已经在前面见过或者见过类似的,所以就不再多讲了。总之我们可以看到,若m_pUnkAutoAgg.p不为空则直接查询,否则创建聚集组件。
与宏COM_INTERFACE_ENTRY_AGGREGATE相比,这个宏似乎更好一些,仅当需要时才会创建,使用更简单。
八、COM_INTERFACE_ENTRY_AUTOAGGREGATE_BLIND( punk, clsid )
看看它的定义:
呵呵,这个宏综合了 COM_INTERFACE_ENTRY_AUTOAGGREGATE() 和 COM_INTERFACE_ENTRY_AGGREGATE_BLIND() 的特点,既可以自动创建也可以很方便地查询聚集组件中的多个接口。不再赘述!!
上一节我们讲了COM_INTERFACE_ENTRY_AGGREGATE,这节要介绍的宏与它很类似。
#define COM_INTERFACE_ENTRY_AGGREGATE_BLIND(punk)/ {NULL,/ (DWORD)offsetof(_ComMapClass, punk),/ _Delegate}, |
从定义上就可以看出,它与上一节介绍宏的唯一区别就在于,它没有指明接口ID!!
所以在它的定义中第一项也是NULL。
这个宏的用法与我们COM_INTERFACE_ENTRY_AGGREGATE一模一样。大家可以参考上一节内容以及ATL的例程COMMAP。
我们来看看AtlInternalQueryInterface()中的相关代码。
ATLINLINE ATLAPI AtlInternalQueryInterface(void* pThis, const _ATL_INTMAP_ENTRY* pEntries, REFIID iid, void** ppvObject) { //如果是IUnknown,.... while (pEntries->pFunc != NULL) { BOOL bBlind = (pEntries->piid == NULL); if (bBlind || InlineIsEqualGUID(*(pEntries->piid), iid)) { if (pEntries->pFunc == _ATL_SIMPLEMAPENTRY) //offset { ATLASSERT(!bBlind); IUnknown* pUnk = (IUnknown*)((int)pThis+pEntries->dw); pUnk->AddRef(); *ppvObject = pUnk; return S_OK; } else { HRESULT hRes = pEntries->pFunc(pThis, iid, ppvObject, pEntries->dw); if (hRes == S_OK || (!bBlind && FAILED(hRes))) return hRes; } } pEntries++; } return E_NOINTERFACE; } 注意变量bBlind: BOOL bBlind = (pEntries->piid == NULL); |
若没指定接口ID,也继续执行后面的操作,可见即使并非我们所需要的IID,也会执行_Delegate.
从上可见,这个宏适用于一个聚集组件有多个接口的情况,这样只要是查询这个聚集组件的接口,就会进入_Delegate函数。但要特别注意的是这个宏的位置!! 比如若是这样的顺序:
BEGIN_COM_MAP COM_INTERFACE_ENTRY_AGGREGATE_BLIND(m_pUnkAggBlind.p) COM_INTERFACE_ENTRY(IOuter) END_COM_MAP |
当查询IOuter接口时就会出错!!!
七、COM_INTERFACE_ENTRY_AUTOAGGREGATE(iid, punk, clsid)
先看看这个宏的定义:
#define COM_INTERFACE_ENTRY_AUTOAGGREGATE(iid, punk, clsid)/ {&iid,/ (DWORD)&_CComCacheData</ CComAggregateCreator< _ComMapClass, &clsid >,/ (DWORD)offsetof(_ComMapClass, punk)/ >::data,/ _Cache}, |
先看看它的典型用法:
class CAutoAgg : public IDispatchImpl< IAutoAgg, &IID_IAutoAgg, &LIBID_AGGREGLib >, public ISupportErrorInfo, public CComObjectRoot, public CComCoClass< CAutoAgg,&CLSID_CAutoAgg > { ...... }; |
与一般的组件并无二样。
class COuter : public CChainBase, public IDispatchImpl, public CComCoClass { BEGIN_COM_MAP(COuter) COM_INTERFACE_ENTRY_AUTOAGGREGATE(IID_IAutoAgg, m_pUnkAutoAgg.p, CLSID_CAutoAgg) END_COM_MAP() CComPtr m_pUnkAutoAgg; }; |
与宏COM_INTERFACE_ENTRY_AGGREGRATE(_)不同,COuter不用在FinalConstruct中创建聚集组件。外部组件会自动创建聚集组件!!!
1。
template < class Creator, DWORD dwVar > _ATL_CACHEDATA _CComCacheData< Creator, dwVar >::data = {dwVar, Creator::Creat eInstance}; |
2。
static HRESULT WINAPI _Cache(void* pv, REFIID iid, void** ppvObject, DWORD dw) { HRESULT hRes = E_NOINTERFACE; _ATL_CACHEDATA* pcd = (_ATL_CACHEDATA*)dw; IUnknown** pp = (IUnknown**)((DWORD)pv + pcd->dwOffsetVar); if (*pp == NULL) hRes = pcd->pFunc(pv, IID_IUnknown, (void**)pp); if (*pp != NULL) hRes = (*pp)->QueryInterface(iid, ppvObject); return hRes; } |
3。
template < class T, const CLSID* pclsid > class CComAggregateCreator { public: static HRESULT WINAPI CreateInstance(void* pv, REFIID/*riid*/, LPVOID* ppv ) { ATLASSERT(*ppv == NULL); ATLASSERT(pv != NULL); T* p = (T*) pv; return CoCreateInstance(*pclsid, p->GetControllingUnknown(), CLSCTX_ALL, IID_IUnknown, ppv); } }; |
因为_Cache,_CComCacheData,CComAggregateCreator这几个类和函数我们已经在前面见过或者见过类似的,所以就不再多讲了。总之我们可以看到,若m_pUnkAutoAgg.p不为空则直接查询,否则创建聚集组件。
与宏COM_INTERFACE_ENTRY_AGGREGATE相比,这个宏似乎更好一些,仅当需要时才会创建,使用更简单。
八、COM_INTERFACE_ENTRY_AUTOAGGREGATE_BLIND( punk, clsid )
看看它的定义:
#define COM_INTERFACE_ENTRY_AUTOAGGREGATE_BLIND(punk, clsid)/ {NULL,/ (DWORD)&_CComCacheData</ CComAggregateCreator< _ComMapClass, &clsid >,/ (DWORD)offsetof(_ComMapClass, punk)/ >::data,/ _Cache}, |
呵呵,这个宏综合了 COM_INTERFACE_ENTRY_AUTOAGGREGATE() 和 COM_INTERFACE_ENTRY_AGGREGATE_BLIND() 的特点,既可以自动创建也可以很方便地查询聚集组件中的多个接口。不再赘述!!