PART III
基本ATL COM 对象
一、应用IUnknown的两个方面:
a) 应用IUnknown的方法,使用:CComObject, CComAggObject 或CComPolyObject。
b) 管理参考计数和外部指针:CComObjectRoot, CComObjectRootEx。
二、其它对象:
a) CComCoClass:定义默认类工厂和聚合。
b) IDispatchImpl:提供默认的IDispatch,支持双接口
三、应用CComObjectRootEx(必不可少):所有ATL 对象必须继承CComObjectRootEx 或 CComObjectRoot。
a) 基于COM映射提供QueryInterface机制。COM映射暴露对象的接口。接口查询使用了CComObjectRootEx::InternalQueryInterface。
b) 添加接口的方法:
BEGIN_COM_MAP(CMyClass)
COM_INTERFACE_ENTERY(IDispatch)
COM_INTERFACE_ENTERY_TEAR_OFF ( IID_ISupportErrorInfo, CMyClass)
END_COM_MAP()
四、 应用CComObject, CComAggObject 和CComPolyObject :
n 在继承链中总是作为最底层的基类。是否应用,决定于是否声明DECLARE_POLY_AGGREGATABLE宏 和 是否聚合。
n 使用CComPolyObject较好,而且如果不使用聚合,花销不大。
n 在创建full control 和IE control时ATL Wizard默认添加DECLARE_POLY_AGGREGATABLE宏。
五、 使用IDispatchImpl模板类提供 IDispatch,支持双接口,可以在VB中使用。
六、 使用IErrorInfo支持错误提示。在接口映射中需要提供ISupportErrorInfo接口。使用的模板类是ISupportErrorInfoImpl。
七、 使用IDispEventImpl提供连接点支持消息事件。使用步骤(需包含头文件):
a) 为每个外部分发对象导入类型库,如(MyServer):
#import “D:/MyServer.dll” raw_interfaces_only, no_namespace, named_guids
b) 为每个外部分发接口分别申明IDispEventImpl接口,如为类CMyObj应用客户接口(IExtEvents1):
public IDispEventImpl<0, CMyObj, &DIID_IExtEvents1, &LIBID_EXTEVENTS1Lib, 1, 0>
c) 申明事件映射,如:
BEGIN_SINK_MAP(comClass)
SINK_ENTRY(id, dispid, func) //样板
SINK_ENTRY(0, Events1, OnClick1) //样例
… // 其它外部事件入口
END_SINK_MAP()
d) 在适宜的时间通报(Advising & Unadvising)连接开始和结束 :
在外部事件和COM对象交互之前,通报连接(Advising);完成与外部接口交互后,通报连接结束(Unadvising)。
八、 使用CComCoClass定义默认类厂和聚合模式,他指定两个宏:
a) DECLARE_CLASSFACTORY //声明类厂为CComClassFactory
b) DECLARE_AGGREGATABLE //声明可聚合,它调用_CreatorClass,继承的类重载默认的行为。
c) 如果用CComClassFactory2,把a)改为:
DECLARE_CLASSFACTORY2(CMyLicense)
d) 其它类厂的宏:
DECLARE_CLASSFACTORY_AUTO_THREAD
DECLARE_CLASSFACTORY_SINGLETON
九、 创建聚合的步骤:
a) 在C++类中添加IUnknown指针,在构造函数中初始化为NULL;
b) 在COM_INTERFACE_ENTRY_AGGREGATE宏的第二个参数使用此指针;
c) 重载FinalConstruct创建聚合;
d) 重载FinalRelease释放IUnknow指针
n 如果在FinalConstruct期间,从聚合使用和释放接口,要在类中添加宏:
DECLARE_PROTECT_FINAL_CONSTRUCT