COM插件模型浅谈

作者: 杜春辉

下载源代码

一、关于普通DLL插件的实现VC知识库里已有文章介绍,但在很多大型的软件中(如ArcGis、Office)中都不是采用这种方法,基于COM的插件在当今的大型软件中应用的更广泛。

二、实现插件离不开三个要素

  1. 插件管理器(即:要使用这些插件的主程)
  2. 插件基本接口(即:插件与管理器都认可的接口标准),在DLL插件中这个要素通常是一个标准的C++头文件,在COM插件中我们常用一个包含基类的接口COM,在这个COM中它只定义接口,不作任何实现。
  3. 插件COM,在这些COM中,它们只实现基类COM库的接口,没有自己的接口。

  本文的例子中TestSvr是第一个要素,是插件管理器,plugin目录下的两个工程是第三个要素是插件COM,Interface code目录下的工程是提供基本类的COM,是我们上面提到的第二个要素。

三、在DLL插件中我们搜索插件的方法是将插件存放在与主程序相对固定的目录下,主程序通过搜索目录文件而搜索插件,在COM插件里我们不能用这种方法搜索插件,这里我们采用的方法是每个COM插件都注到一下固定的COM分组中,主程序在COM分组中搜索出插件 。
以下的代码是将一个COM注册、反注册到某一个COM组:
void SpecialReg(GUID ID_SubItem,BOOL bRegister)
{
	ICatRegister* pICatRegister = NULL ;
	HRESULT hr = ::CoCreateInstance(CLSID_StdComponentCategoriesMgr,
		                            NULL, 
					 CLSCTX_ALL, 
					 IID_ICatRegister,
		                            (void**)&pICatRegister) ;
	if (FAILED(hr))
	{
		ErrorMessage("Could not create the ComCat component.", hr);
		return ;
	}
	CATEGORYINFO CatInfo ;
	CatInfo.catid               = CATID_MyCategory ;
	CatInfo.lcid                = LOCALE_SYSTEM_DEFAULT ;
	wcscpy(CatInfo.szDescription,sCateGoryName) ;
	if (bRegister)
	{
		hr = pICatRegister->RegisterCategories(1, &CatInfo) ;
		hr = pICatRegister->RegisterClassImplCategories(ID_SubItem,
			                                    1, 
							&CATID_MyCategory) ;
	}
	else
	{
		hr = pICatRegister->UnRegisterClassImplCategories(ID_SubItem,
			                                    1, 
							&CATID_MyCategory);
		ICatInformation* pICatInformation = NULL ;
		hr = pICatRegister->QueryInterface(IID_ICatInformation, 
			                           (void**)&pICatInformation) ;
		IEnumCLSID* pIEnumCLSID = NULL ;
		hr = pICatInformation->EnumClassesOfCategories(1, 
			                  &CATID_MyCategory, 
					0, 
					NULL, 
					&pIEnumCLSID) ;
		CLSID clsid ;
		hr = pIEnumCLSID->Next(1, &clsid, NULL) ;
		if (hr == S_FALSE)
		{
			hr = pICatRegister->UnRegisterCategories(1, &CATID_MyCategory) ;
		}
		pIEnumCLSID->Release() ;
		pICatInformation->Release() ;
	}
	if (pICatRegister)
	{
		pICatRegister->Release() ;
	}
}
      
以下的代码是从COM组中列举各个COM组件
ICatInformationPtr pICatInformation(CLSID_StdComponentCategoriesMgr);
IEnumCLSID* pIEnumCLSID = NULL ;
HRESULT hr = pICatInformation->EnumClassesOfCategories(1, 
				     &CATID_RdExcelExportCategory, 
				     0, 
				     NULL, 
				     &pIEnumCLSID) ;

ASSERT(SUCCEEDED(hr)) ;

long nComandID = _BASE_COMMAND_ID_;
CLSID clsid ;
while ((hr = pIEnumCLSID->Next(1, &clsid, NULL)) == S_OK)
{
	RDINTERFACELib::ICommandPtr pCommand(clsid);
}      
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值