用ATL为组件加入注册支持

用ATL为组件加入注册支持

hanlray@gmail.com

Revision: 1.0 Date: 2005/12/10


如前文所述,在某些情况下我们需要一种不需要注册的COM组件,ATL完全支持这种情况,此时的COM组件除了在创建方法上较为特殊外(用ATL::CComObject的提供的静态方法CreateInstance来创建),和一个普通的C++类无异;另一方面,这样的组件也有重新被要求注册的可能性,如何为其加入这样的支持呢?

首先,应该为该组件分配一个GUID,并指定其所用的线程模型,progid等信息。用VC++的所谓属性化编程,应该类似下面这样:

[coclass, progid("MyCoClass.coclass.1"), vi_progid("MyCoClass.coclass"), 
appobject, uuid("9E66A294-4365-11D2-A997-00C04FA37DDB")]
class CMyClass ... 

	

第二步,为该组件类加入OBJECT_ENTRY_AUTO宏。CoCreateInstance函数的基本流程应该是这样的(对DLL形式的COM模块而言,以下同):根据CLSID在注册表中找到该组件所在的COM模块的路径,加载它,调用其导出的DllGetClassObject得到该组件的工厂对象,然后用该工厂对象创建一个组件实例。在ATL中这个导出的DllGetClassObject是由CAtlDllModuleT类来实现的,该类保存了一个所谓的Object Map,其中的每一项对应一个组件类,key为组件类的guid,value为组件类的相关信息,包括取得该组件类的工厂对象的函数指针,更新该组件类的注册信息的函数指针等。 当导出的DllGetClassObject被调用时,CAtlDllModuleT就在该Object Map中查找请求的组件类,调用相应的取得组件工厂对象的函数。OBJECT_ENTRY_AUTO宏就是把指定的组件类加到该Object Map中。

最后,创建一个Registrar Script资源,在组件类中加入DECLARE_REGISTRY_RESOURCEID宏。如第二步所述,CoCreateInstance要求注册表中必须要有该组件的注册信息,这一般是用regsvr32程序来写入的;为了支持regsvr32,DLL模块一般都会导出两个函数:DllRegisterServer/DllUnregisterServer,分别实现注册与反注册。CAtlDllModuleT类已有这两个函数的实现,不过它依赖组件类提供的注册信息。当导出的DllRegisterServer/DllUnregisterServer被调用时,CAtlDllModuleT就会针对Object Map中的每一项,调用相应的更新注册表的函数,其结果就把组件的注册信息写入了注册表。 OBJECT_ENTRY_AUTO宏会以组件类的静态函数UpdateRegistry作为更新该组件注册信息的函数,所以组件类还需要一个UpdateRegistry函数,这就是由DECLARE_REGISTRY_RESOURCEID宏来实现的,该宏的参数是一个resource ID,标识一个REGISTRY资源;该资源实际上是一个Registrar Script, 用BNF的语法描述了更新注册表的操作,下面是一个组件的例子:

HKCR
{
	ATLAsync.ATLAsync.1 = s 'ATLAsync Class'
	{
		CLSID = s '{012F24D4-35B0-11D0-BF2D-0000E8D0D146}'
		'Insertable'
	}
	ATLAsync.ATLAsync = s 'ATLAsync Class'
	{
		CLSID = s '{012F24D4-35B0-11D0-BF2D-0000E8D0D146}'
		CurVer = s 'ATLAsync.ATLAsync.1'
	}
	NoRemove CLSID
	{
		ForceRemove {012F24D4-35B0-11D0-BF2D-0000E8D0D146} = s 'ATLAsync Class'
		{
			ProgID = s 'ATLAsync.ATLAsync.1'
			VersionIndependentProgID = s 'ATLAsync.ATLAsync'
			InprocServer32 = s '%MODULE%'
			{
				val ThreadingModel = s 'Apartment'
			}
			ForceRemove 'Control'
			ForceRemove 'ToolboxBitmap32' = s '%MODULE%, 1'
			'MiscStatus' = s '0'
			{
			    '1' = s '131473'
			}
			'TypeLib' = s '{012F24C1-35B0-11D0-BF2D-0000E8D0D146}'
			'Version' = s '1.0'
		}
	}
}
	

具体更新注册表的操作会由Registry Script的引擎帮我们完成,我们所要做的只是按照规定的语法告诉其更新注册表的逻辑。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值