一 概要
ATL库(Active Template Library)动态模板库,它是一套C++模板库。使用ATL能够快速的开发出高效简洁的代码,同时对COM组件的开发提供了最大限度的代码自动生成以及可视化支持。封装了COM组件的各种细节和COM SDK,可以方便用户进行组件开发。
COM的实现在ATL产生以前,是使用COM SDK直接开发COM组件。ATL的基本目标就是使COM应用开发尽可能自动化。ATL的各个版本对Microsoft的基于COM的各种新的组件技术如MTS、ASP等都有很好的支持,ATL对新技术的反应速度大大快于MFC。
常用的ATL类:
组件的实现:
组件的创建:CComObjectRootBase-->-CComObjectRootEx->CImpMath-->CComObject;
二 类厂-----组件的创建
类厂:用于创建组件的组件,类厂也是一个组件,作用创建其它组件;类厂的接口IClassFactory;ATL:CComCoClass
类厂的实现:
类厂创建:使用_Module.GetClassObject获取指定组件的类厂;使用类厂创建组件对象,并返回接口
三 组件的使用
微软提供CoCreateInstance创建组件并返回接口
STDAPI CoCreateInstance(
REFCLSID rclsid, //组件ID
LPUNKNOWN pUnkOuter, //聚合接口,不使用时,NULL
DWORD dwClsContext, //组件的运行方式
REFIID riid, //接口的ID
LPVOID *ppv //接口的地址
);
3.1. 使用ATL向导生成的工程中包含的四个函数
3.2 组件注册
3.3 组件的使用
3.4 组件的创建
3.5 COM的智能指针类: 用于自动维护接口指针,包括创建和释放;CComPtr -完成基本接口指针的维护;CComQIPtr-类似于CComPtr,可以自动完成查询功能
一 创建ATL项目COMMath
1.新建ATL项目COMMath:下一步-->应用程序类型:动态链接库DLL;支持选项:支持COM+1.0,支持部件注册器-->完成。
2.添加MathAdd类:右击--添加--类-->选择ATL简单对象-->简称:MathAdd;别的默认;COM ProgID:COMMath.MathAdd-->下一步,下一步,完成。
3.添加接口方法Add():在类视图中,右击IMathAdd接口,选择 添加---方法 -->方法名:Add,参数特性 HRESULT Add([in] int nAdd1, [in] int nAdd2, [out,retval] int* nResult);
4.添加Add()方法的实现:在MathAdd.cpp中添加:
STDMETHODIMP CMathAdd::Add(int nAdd1, int nAdd2, int* nResult)
{
*nResult=nAdd1+nAdd2;
return S_OK;
}
二创建使用ATL项目COMMath的MFC dialog的UseCOMMath项目
1.在用一个解决方案中创建MFC dialog UseCOMMath项目
2.在UseCOMMath.cpp中:
BOOL CUseCOMMathApp::InitInstance()
{
CoInitialize(0); // 现在初始化COM
...
return FALSE;
}
int CUseCOMMathApp::ExitInstance()
{
CoUninitialize();// 卸载COM
return CWinApp::ExitInstance();
}
3.按钮代码
#include "../COMMath/COMMath_i.h"
#include "../COMMath/COMMath_i.c"
void CUseCOMMathDlg::OnBnClickedButton1()
{
IUnknown* piUnknown=NULL;
CoCreateInstance(CLSID_MathAdd,NULL,CLSCTX_SERVER,IID_IUnknown,(LPVOID*)&piUnknown);//创建组件,并返回IUnknown接口
IMathAdd* piMath=NULL;
piUnknown->QueryInterface(IID_IMathAdd,(LPVOID*)&piMath);//查询IMathAdd接口
piUnknown->Release();//释放IUnknown接口
int nResult=0;
piMath->Add(10,10,&nResult);//使用IMathAdd接口
piMath->Release();//释放IMathAdd接口
CString strResult;
strResult.Format(L"nResult:%d",nResult);
MessageBox(strResult); //输出结果
}
void CUseCOMMathDlg::OnBnClickedButton2()
{
IMathAdd* piMath=NULL;
CoCreateInstance(CLSID_MathAdd,NULL,CLSCTX_SERVER,IID_IMathAdd,(LPVOID*)&piMath);//创建组件,返回IMathAdd接口
int nResult=0;
piMath->Add(20,-30,&nResult);//使用IMathAdd接口
piMath->Release();//释放IMathAdd接口
CString strResult;
strResult.Format(L"nResult:%d",nResult);
MessageBox(strResult);//输出结果
}
void CUseCOMMathDlg::OnBnClickedButtonProgid()
{
CLSID clsid={0};
CLSIDFromProgID(L"COMMath.MathAdd",&clsid);//根据ProgID来获取clsid
IMathAdd* piMath=NULL;
HRESULT hr=CoCreateInstance(clsid,NULL,CLSCTX_SERVER,IID_IMathAdd,(LPVOID*)&piMath);//创建组件,并返回IMathAdd接口
int nResult=0;
if (piMath)
{
piMath->Add(-50,100,&nResult);//使用IMathAdd接口
piMath->Release();//释放IMathAdd接口
CString strResult;
strResult.Format(L"nResult:%d",nResult);
MessageBox(strResult);//输出结果
}
}
void CUseCOMMathDlg::OnBnClickedButtonCcomptr()
{
CComPtr piUnknown;
piUnknown.CoCreateInstance(L"COMMath.MathAdd");
CComPtr piMath;
piUnknown->QueryInterface(&piMath);
int nResult=0;
piMath->Add(50,50,&nResult);//使用IMathAdd接口
//piMath->Release();//释放IMathAdd接口
CString strResult;
strResult.Format(L"nResult:%d",nResult);
MessageBox(strResult);
}
void CUseCOMMathDlg::OnBnClickedButtonCcomqiptr()
{
CComQIPtr piMath;
piMath.CoCreateInstance(L"COMMath.MathAdd");
int nResult=0;
piMath->Add(100,100,&nResult);//使用MathAdd接口
//piMath->Release();//释放IMathAdd接口
CString strResult;
strResult.Format(L"nResult:%d",nResult);
MessageBox(strResult);//输出结果
}
4.结果: