编写可复用性更好的C++代码:Band对象和COMToys(2)
2006-07-21 11:44:10 来源:WEB开发网 閵嗭拷

// 例子中把脚本都放在了应用程序的资源中MyBands.rc
IDR_INFOBAND REGISTRY DISCARDABLE "BandObj.rgs"
IDR_COMMBAND REGISTRY DISCARDABLE "BandObj.rgs"
IDR_DESKBAND REGISTRY DISCARDABLE "BandObj.rgs"
不过,三个不同的COM对象怎么可能使用相同的注册脚本呢?它们不是有不同的名字和类IDs吗? 这就是IRegistrar的好处之所在。看一下注册脚本BandObj.rgs。到处是%CLSID%, %ClassName%, 和 %MODULE% ,这些标志是什么意思呢? 这些都是变量。在处理脚本之前,注册器会用实际的值(类ID,类名和模块名)替代这些变量。那它怎么知道使用什么值呢?因为你告诉它了--或者说是BandObj告诉它了。你可能注意到了在UpdateRegistry中有一个对OnInitRegistryVariables的调用。就是在这个地方,BandObj定义了它的变量。
BOOL CBandObjFactory::OnInitRegistryVariables(IRegistrar* pReg)
{
USES_CONVERSION;
pReg->AddReplacement(OLESTR("CLSID"), StringFromCLSID(m_clsid));
pReg->AddReplacement(OLESTR("MODULE"), T2OLE(GetModuleName()));
pReg->AddReplacement(OLESTR("ClassName"), T2OLE(GetClassName()));
return TRUE;
}
下面是我在CBandObjFactory中建立的全部变量列表,它们都自动由BandObj定义。
%CLSID% = class ID (GUID)(COleObjectFactory::m_clsid)
%MODULE% = DLL的全路径名
%Title% = 标题(资源子串 0)
%ClassName% = 人可读的COM类名 (资源子串 1)
%ProgID% = ProgID (资源子串 2)
要想添加自己的变量,如%TimeStamp% 或者 %MyReleaseVersion%,,只要派生一个新类厂并重载OnInitRegistryVariables就可以了。不要忘了调用基类,因为MFC为每一个类厂调用UpdateRegistry,而对每个类而言,变量都被重新初始化。所以在MyBands中,第一个类厂的%CLSID% 是 CLSID_MYINFOBAND,第二个类厂的%CLSID% 是 CLSID_ MYCOMMBAND,而第三个类厂的%CLSID% 是 CLSID_MYDESKBAND。同一个脚本处理三种对象的注册,酷毙了!。
IRegistrar这么酷,所以我写了自己的命令行实用程序 RGSRUN来加载RGS文件,它对于测试和调试脚本或者从注册表种删除多余的垃圾都非常有用,有些功能是REGEDIT所没有的。这个实用程序与本文的例子一起提供。我在autoexec.bat文件中使用RGSRUN加载一个文件:autoexec.rgs,其中设置了不同的Explorer选项,Windows每次启动都会自动完成加载。
种类注册
如果你仔细阅读本文,就会注意到前面提到的脚本文件中没有关于band对象种类注册的内容。为什么呢?BandObj在哪里注册它的种类信息呢?我用了另外一个变量来做这件事情,它就是%catid%,而COM库中也总是有接口应用于此,种类也不例外。正式的种类注册方法是通过ICatRegister实现的:
BOOL CBandObjFactory::UpdateRegistry(BOOL bReg)
{
......
// 使用ICatRegister 注册/注销种类
CTCatRegister iCat;
REFIID clsid = m_clsid;
hr = bRegister ?
iCat->RegisterClassImplCategories(clsid, 1, &m_catid) :
iCat->UnRegisterClassImplCategories(clsid, 1, &m_catid);
// 返回,旁路掉MFC
return hr==S_OK;
}
由此可见,使用ATL智能指针,COMToys类以及CTCatRegister使编程更轻松。你只要声明实例就行了。(待续)
更多精彩
赞助商链接