常见问题总结6
注意变量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) 参ATL例程COMMAP
先看看这个宏的定义:
#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 ) 参ATL例程COMMAP
看看它的定义:
#define COM_INTERFACE_ENTRY_AUTOAGGREGATE_BLIND(punk, clsid)\
{NULL,\
(DWORD)&_CComCacheData<\
CComAggregateCreator< _ComMapClass, &clsid >,\
(DWORD)offsetof(_ComMapClass, punk)\
>::data,\
_Cache},