荔园在线

荔园之美,在春之萌芽,在夏之绽放,在秋之收获,在冬之沉淀

[回到开始] [上一篇][下一篇]


发信人: Deny (冬天来咯), 信区: Program
标  题: 五.COM_INTERFACE_ENTRY_AGGREGATE(iid, punk) 参AT
发信站: 荔园晨风BBS站 (Thu Nov 15 20:09:18 2001), 转信


五.COM_INTERFACE_ENTRY_AGGREGATE(iid, punk) 参ATL例程COMMAP


这一节中将介绍ATL中用于聚集对象的宏。聚集对象的概念请参阅其它参考书。
现在先看一看这个宏的典型用法:
class CAgg :
public IDispatchImpl,
public ISupportErrorInfo,
public CComObjectRoot,
public CComCoClass
{
.....
};
CAgg是一个聚集类,它的实现与一般的ATL组件没有区别,只是注意在它的类定义
中不
要加入DECLARE_NO_AGGREGATABLE.
class COuter :
public CChainBase,
public IDispatchImpl,
public CComCoClass
{
HRESULT FinalConstruct();
void FinalRelease();
BEGIN_COM_MAP(COuter)
COM_INTERFACE_ENTRY_AGGREGATE(IID_IAgg, m_pUnkAgg.p)
END_COM_MAP()
DECLARE_GET_CONTROLLING_UNKNOWN()
CComPtr m_pUnkAgg;
};

COuter包含了聚合组件CAgg,它包含了几个不同之处:
(1)加入了COM_INTERFACE_ENTRY_AGGREGATE(IID_IAgg, m_pUnkAgg.p)宏。
#define COM_INTERFACE_ENTRY_AGGREGATE(iid, punk)\
{&iid,\
(DWORD)offsetof(_ComMapClass, punk),\
_Delegate},
offsetof我们在上一节中已经见过,可以猜到它求的就是punk在类中的位置。也就

是m_pUnkAgg在COuter中的位置。
(2)加入了宏DECLARE_GET_CONTROLLING_UNKNOWN(),其定义为:
#define DECLARE_GET_CONTROLLING_UNKNOWN() public:\
virtual IUnknown* GetControllingUnknown() {return GetUnknown();}
我们也必要继续深究下去,仅从字面意思就可以看出这个函数将返回组件的
IUnknown
指针。
(3)在COuter中加入一个成员变量:CComPtr m_pUnkAgg;
m_pUnkAgg将用于获得被聚集组件的IUnknown指针。
(4)重载了FinalConstruct,FinalRelease
HRESULT COuter::FinalConstruct()
{
IUnknown* pUnkOuter = GetControllingUnknown();
HRESULT hRes = CoCreateInstance(CLSID_CAgg, pUnkOuter,
CLSCTX_INPROC_SERVER, IID_IUnknown, (void**)&m_pUnkAgg);
if (hRes != S_OK)
return hRes;
return S_OK;
}
void COuter::FinalRelease()
{
m_pUnkAgg.Release();
.....
}
当创建组件COuter后将会调用FinalConstruct,所以会在这里创建聚集组件。原则

聚集组件可以仅在需要的时候才创建,但也可以随着包含它的组件一起创建。聚集
组件
的创建没什么特别之处,只是要注意它将查询IUnknown指针,并返回给
m_pUnkAgg.外部
组件将通过m_pUnkAgg操作聚集组件。另外注意到使用pUnkOuter作为
CoCreateInstance
的参数,这将导致创建CComAggObject对象,内部包含一个CComContainedObject
的包含对象。向上一节中的CComCachedTearOff<>类似,CComAggObject也不是
从COuter派生的,所以真正的组件对象不是CComAggObject对象,而是它内部包
含的CComContainedObject对象。同样pUnkOuter得到的将是CComAggObject<>的
IUnknown指针,也同样调用它的QueryInterface会转而调用CComContainedObject

_InternalQueryInterface函数(呵呵,现在可都还是我猜的,看我猜的对不对吧


运行pOuter->QueryInterface(IID_IAgg, (void **)&pAgg1)
函数堆栈一:
9.ATL::AtlInternalQueryInterface(...)
8.ATL::CComObjectRootBase::InternalQueryInterface(...)
7.CAgg::_InternalQueryInterface(...)
6.ATL::CComAggObject::QueryInterface(...)
5.ATL::CComObjectRootBase::_Delegate(...)
4.ATL::AtlInternalQueryInterface(...)
3.ATL::CComObjectRootBase::InternalQueryInterface(...)
2.COuter::_InternalQueryInterface(...)
1.ATL::CComObject::QueryInterface(...)

解释:
1-5:这几步函数调用我们已经见了很多次了,因为在这个宏定义使用了
_Delegate,所以
将调用CComObjectRootBase::_Delegate(...).
static HRESULT _Delegate(void* pv,REFIID iid,void** ppvObject,DWORD
dw)
{
HRESULT hRes = E_NOINTERFACE;
IUnknown* p = *(IUnknown**)((DWORD)pv + dw);
if (p != NULL)
hRes = p->QueryInterface(iid, ppvObject);
return hRes;
}
第二句话的含义我们在上一节中已经见过了,最后的结果p=COuter::m_pUnkAgg.

6:正如我们刚才所料,现在调用的是CComAggObject::QueryInterface()
STDMETHOD(QueryInterface)(REFIID iid, void ** ppvObject)
{
//如果查询的是IUnknown,则....
else
hRes = m_contained._InternalQueryInterface(iid, ppvObject);
return hRes;
}
也正如我们所料,将交给它的包含对象去做.(这段代码在上一节好象也见过是吧,呵
呵)
7-9:同上一节一样,将交给CAgg::_InternalQueryInterface(...),剩下的工作将
由CAgg
完成了。最后返回的指针实际上将是CComContainedObject组件的接口指针。



运行pAgg1->QueryInterface(IID_IAgg, (void **)&pAgg2)
函数堆栈二:
9.CAgg::_InternalQueryInterface(...)
8.ATL::CComAggObject::QueryInterface(...)
7.ATL::CComObjectRootBase::_Delegate(...)
6.ATL::AtlInternalQueryInterface(...)
5.ATL::CComObjectRootBase::InternalQueryInterface(...)
4.COuter::_InternalQueryInterface(...)
3.ATL::CComObject::QueryInterface(...)
2.ATL::CComObjectRootBase::OuterQueryInterface(...)
1.ATL::CComContainedObject::QueryInterface(...)

解释:
1-9:浏览整个堆栈,与我们上一节所见的堆栈二太相近了,这是因为都是使用了包
含对
象。包含对象起了个代理的作用,他先把查询交给外部对象(COuter)去做(第1,2步
),
当外部对象发现要查询的是聚集组件的接口时(IAgg),就会再把查询交还给它保留

聚集组件的指针(m_pUnkAgg,第7步中,注意这不是真正的聚集组件),m_pUnkAgg再把

询交给包含对象(第8步中),包含对象再把查询交给真正实现接口的类CAgg(第9步).

若外部对象发现要查询的是外部组件的接口时,那就很简单了,直接查询就行了。

样就防止了外部组件与聚集组件查询操作的不一致性。
唉,真个过程真麻烦,不过还好,与上一节的宏很类似。相关的源码可参看上一节


--
今天没什么好玩的事编程资料:1.201/study/my document/,也许有你要的东西      ★
               ★             ┬┬ /
                     ★     ▕▂▂●--
   ★      ★                 ██
                            ▂██▂
███████████████████~~~~*        OICQ:86395

※ 来源:·荔园晨风BBS站 bbs.szu.edu.cn·[FROM: 192.168.1.201]


[回到开始] [上一篇][下一篇]

荔园在线首页 友情链接:深圳大学 深大招生 荔园晨风BBS S-Term软件 网络书店