用ATL建立轻量级的COM对象(七)

330 篇文章 4 订阅 ¥19.90 ¥99.00
本文详细介绍了如何使用ATL创建轻量级的COM对象,特别是关于对象的注册和自注册机制。从为什么要使用ATL开始,逐步讲解起步、实现IUnknown、接口实现以及如何避免过度抽象。重点探讨了ATL的注册脚本技术,包括REGISTRY资源文件的使用、IRegistrar接口以及如何在注册脚本中添加自定义替换变量,以实现如安装日期等动态信息的记录。
摘要由CSDN通过智能技术生成

第一部分:为什么要使用ATL。

第二部分:起步篇。

第三部分:实现IUnknown。

第四部分:实现接口。

第五部分:不要过分抽象。

第六部分:输出你的类。

ATL和注册表

CComModule 提供了两个方法用于自注册:一个是RegisterServer,另外一个是 UnregisterServer。这两个方法使用传递到 Init 例程的对象映射来完成实际的工作。正像我前面所提到的那样,每一个对象映射入口都包含 pfnUpdateRegistry 函数指针,这个指针必须由类实现者提供。ATL最初的版本所提供的例程为 CLSID 自动添加标准注册入口,从而使缺省行为的实现很容易。可惜这些例程不具备很好的可扩展性,而且如果服务器的需求超过了正常 InprocServer32 入口所包含的内容的话,就必须自己用手工来编写注册代码。

随着组件种类(categories)和 AppIDs 概念的出现,几乎就再没有服务器能认可由ATL1.0提供的标准注册入口。在ATL1.1及以后的版本中,首选的自注册技术是使用注册脚本,它非常灵活。这个技术需要 IRegistrar 接口的COM实现,它既可以静态链接以降低依赖性,也可以用 CoCreateInstance 动态绑定来最小化代码尺寸。

注册脚本只是个文本文件,它列出必须为给定的 CLSID 添加什么入口。注册脚本文件默认的扩展名为RGS,并作为定制的 REGISTRY 类型资源被添加进可执行文件。注册脚本的语法十分简单,归纳起来为:

1. [NoRemove|ForceRemove|val] Name [ = s|d ''''Value''''
2. {
3. ... 用于子键的脚本条目
4. }

NoRemove 前缀表示在进行注销时不删除这个键。ForceRemove 前缀表示在写这个键之前删除当前的键和子键。Val 前缀表示这个入口是个命名的值,而不是一个键。s和d值前缀分别表示REG_SZ 或 REG_DWORD。ATL的解析机制既可以识别 HKEY_CLASSES_ROOT 等标准的注册表键,也能识别HKCR之类的缩写表示。

下面是个脚本注册的例子:REGEDIT4

1. REGEDIT4
2. [HKEY_CLASSES_ROOT\CLSID\{XXX}]
3. @=My Class
4. [HKEY_CLASSES_ROOT\CLSID\{XXX}\InprocServer32]
5. @=C:\foo\bar.dll
6. ThreadingModel=Free

其对应的注册脚本如下:

01. HKCR {
02. NoRemove CLSID {
03. ForceRemove {XXX} = s ''''My Class'''' {
04. InprocServer32 = s ''''%MODULE%'''' {
05. val ThreadingModel = s ''''Free''''
06. }
07. }
08. }
09. }

在使用资源脚本的时候,你的类 UpdateRegistry 方法可以轻松地通过DECLARE_ REGISTRY_RESOURCEID宏定义,它有一个资源ID(通常在resource.h中定义)作为参数:

1. class CPager : public
2. CComObjectRoot,public  
3. IPager
4. CComCoClass {
5. DECLARE_REGISTRY_RESOURCEID(IDR_PAGER)
6. };

这个宏仅仅定义了 UpdateRegistry 方法,它调用内建在 CComModule 中的方法UpdateRegistryFromResource。这个方法有调用资源脚本的解析机制。

在上面显示的注册脚本中,所有出现 %MODULE% 的地方将被实际的 GetModuleFileName 调用结果所代替。如果你需要根据动态运行值添加额外的注册条目,可以添加其它的在注册之前能被置换的串,而不是用 %MODULE%。为此,首先要选用一个新的置换变量,用百分符号限定变量名。例如:

1. DateInstalled = s ''''%CURRENTDATE%''''

然后丁一个定制的UpdateRegistry方法代替使用DECLARE_REGISTRY_ RESOURCEID宏,在你的方法中,建立一个名字-值对置换表,提供给模块的注册引擎。

下面是用包含当前日期的串来替换%CURRENTDATE%变量的一个例子:

01. static HRESULT WINAPI
02. CPager::UpdateRegistry(BOOL b) {
03. OLECHAR wsz [1024]; SYSTEMTIME st; 
04. GetLocalTime(&st);
05. wsprintfW(wsz, L"%d/%d/%d", st.wMonth, st.wDay,
06. st.wYear);
07. _ATL_REGMAP_ENTRY rm[] = {
08. { OLESTR("CURRENTDATE"), wsz}, { 0, 0 },
09. };
10. return _Module.UpdateRegistryFromResource(IDR_PAGER,b, rm);
11. }

这个代码和注册脚本最后的运行结果是注册键 DateInstalled 将包含安装时的日期。(待续)


http://www.vckbase.com/index.php/wv/190.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值