参考:
- VS: VS2015创建ATL
- VC:VC6.0创建ATL
实例
1. 包含两个接口: Student,Teacher
2. Student接口包含5个函数(方法)
3. Teacher接口包含3个函数(方法)
创建COM组件 ATL
1. 在接口对象文件("Student.h")添加以下代码:
// Student.h : CStudent 的声明
#pragma once
#include "resource.h" // 主符号
#include <vector>
#include "VsAtlProjectOne_i.h"
#if defined(_WIN32_WCE) && !defined(_CE_DCOM) && !defined(_CE_ALLOW_SINGLE_THREADED_OBJECTS_IN_MTA)
#error "Windows CE 平台(如不提供完全 DCOM 支持的 Windows Mobile 平台)上无法正确支持单线程 COM 对象。定义 _CE_ALLOW_SINGLE_THREADED_OBJECTS_IN_MTA 可强制 ATL 支持创建单线程 COM 对象实现并允许使用其单线程 COM 对象实现。rgs 文件中的线程模型已被设置为“Free”,原因是该模型是非 DCOM Windows CE 平台支持的唯一线程模型。"
#endif
using namespace ATL;
using namespace std;
struct Student
{
CHAR *pName;
ULONG unNO;
UINT unAge;
CHAR *pAddress;
};
// CStudent
class ATL_NO_VTABLE CStudent :
public CComObjectRootEx<CComSingleThreadModel>,
public CComCoClass<CStudent, &CLSID_Student>,
public IDispatchImpl<IStudent, &IID_IStudent, &LIBID_VsAtlProjectOneLib, /*wMajor =*/ 1, /*wMinor =*/ 0>
{
public:
CStudent()
{
}
DECLARE_REGISTRY_RESOURCEID(IDR_STUDENT)
BEGIN_COM_MAP(CStudent)
COM_INTERFACE_ENTRY(IStudent)
COM_INTERFACE_ENTRY(IDispatch)
END_COM_MAP()
DECLARE_PROTECT_FINAL_CONSTRUCT()
HRESULT FinalConstruct()
{
return S_OK;
}
void FinalRelease()
{
}
private:
//学生数据
vector<Student> m_vStudent;
public:
//增加学生信息
STDMETHOD(AddStuInfo)(CHAR* pStuName, ULONG unStuNO, UINT unStuAge, CHAR *pAddress);
//通过姓名获取年龄
STDMETHOD(GetStuAgeFromName)(CHAR* pStuName, UINT* pStuAge);
//通过姓名获取学号
STDMETHOD(GetStuNOFromName)(CHAR* pStuName, UINT* pnStuNO);
//通过姓名获取地址
STDMETHOD(GetStuAddressFromName)(CHAR* pStuName, CHAR** pnStuAddress);
//获取学生总数
STDMETHOD(GetStuNumber)(UINT* punStuNumber);
};
OBJECT_ENTRY_AUTO(__uuidof(Student), CStudent)
2. 在接口对象文件("Student.cpp")添加以下代码:
// Student.cpp : CStudent 的实现
#include "stdafx.h"
#include "Student.h"
// CStudent
//增加学生信息
STDMETHODIMP CStudent::AddStuInfo(CHAR* pStuName, ULONG unStuNO, UINT unStuAge, CHAR *pAddress)
{
AFX_MANAGE_STATE(AfxGetStaticModuleState());
Student StudentInst;
StudentInst.pName = pStuName;
StudentInst.unNO = unStuNO;
StudentInst.unAge = unStuAge;
StudentInst.pAddress = pAddress;
m_vStudent.push_back(StudentInst);
return S_OK;
}
//通过姓名获取年龄
STDMETHODIMP CStudent::GetStuAgeFromName(CHAR* pStuName, UINT* pStuAge)
{
AFX_MANAGE_STATE(AfxGetStaticModuleState());
vector<Student>::iterator itStu;
for (itStu = m_vStudent.begin(); itStu != m_vStudent.end(); itStu++)
{
if (strcmp((*itStu).pName, pStuName) == 0)
{
*pStuAge = (*itStu).unAge;
break;
}
}
return S_OK;
}
//通过姓名获取学号
STDMETHODIMP CStudent::GetStuNOFromName(CHAR* pStuName, UINT* pnStuNO)
{
AFX_MANAGE_STATE(AfxGetStaticModuleState());
vector<Student>::iterator itStu;
for (itStu = m_vStudent.begin(); itStu != m_vStudent.end(); itStu++)
{
if (strcmp((*itStu).pName, pStuName) == 0)
{
*pnStuNO = (*itStu).unNO;
break;
}
}
return S_OK;
}
//通过姓名获取地址
STDMETHODIMP CStudent::GetStuAddressFromName(CHAR* pStuName, CHAR** pnStuAddress)
{
AFX_MANAGE_STATE(AfxGetStaticModuleState());
vector<Student>::iterator itStu;
for (itStu = m_vStudent.begin(); itStu != m_vStudent.end(); itStu++)
{
if (strcmp((*itStu).pName, pStuName) == 0)
{
*pnStuAddress = (*itStu).pAddress;
break;
}
}
return S_OK;
}
//获取学生总数
STDMETHODIMP CStudent::GetStuNumber(UINT* punStuNumber)
{
AFX_MANAGE_STATE(AfxGetStaticModuleState());
*punStuNumber = m_vStudent.size();
return S_OK;
}
3. 在接口对象文件("Teacher.h")添加以下代码:
// Teacher.h : CTeacher 的声明
#pragma once
#include "resource.h" // 主符号
#include <vector>
#include "VsAtlProjectOne_i.h"
struct Teacher
{
CHAR *pName;
ULONG unNO;
};
#if defined(_WIN32_WCE) && !defined(_CE_DCOM) && !defined(_CE_ALLOW_SINGLE_THREADED_OBJECTS_IN_MTA)
#error "Windows CE 平台(如不提供完全 DCOM 支持的 Windows Mobile 平台)上无法正确支持单线程 COM 对象。定义 _CE_ALLOW_SINGLE_THREADED_OBJECTS_IN_MTA 可强制 ATL 支持创建单线程 COM 对象实现并允许使用其单线程 COM 对象实现。rgs 文件中的线程模型已被设置为“Free”,原因是该模型是非 DCOM Windows CE 平台支持的唯一线程模型。"
#endif
using namespace ATL;
using namespace std;
// CTeacher
class ATL_NO_VTABLE CTeacher :
public CComObjectRootEx<CComSingleThreadModel>,
public CComCoClass<CTeacher, &CLSID_Teacher>,
public IDispatchImpl<ITeacher, &IID_ITeacher, &LIBID_VsAtlProjectOneLib, /*wMajor =*/ 1, /*wMinor =*/ 0>
{
public:
CTeacher()
{
}
DECLARE_REGISTRY_RESOURCEID(IDR_TEACHER)
BEGIN_COM_MAP(CTeacher)
COM_INTERFACE_ENTRY(ITeacher)
COM_INTERFACE_ENTRY(IDispatch)
END_COM_MAP()
DECLARE_PROTECT_FINAL_CONSTRUCT()
HRESULT FinalConstruct()
{
return S_OK;
}
void FinalRelease()
{
}
private:
//老师信息
vector<Teacher> m_vTeacher;
public:
//增加老师信息
STDMETHOD(AddTeacherInfo)(CHAR* pTeaName, UINT unTeaNO);
//通过姓名工号
STDMETHOD(GetTeaNOFromName)(CHAR* pTeaName, ULONG* unTeaNO);
//获取老师总数
STDMETHOD(GetTeaNumber)(UINT* punTeaNumber);
};
OBJECT_ENTRY_AUTO(__uuidof(Teacher), CTeacher)
4. 在接口对象文件("Teacher.cpp")添加以下代码:
// Teacher.cpp : CTeacher 的实现
#include "stdafx.h"
#include "Teacher.h"
// CTeacher
//增加老师信息
STDMETHODIMP CTeacher::AddTeacherInfo(CHAR* pTeaName, UINT unTeaNO)
{
AFX_MANAGE_STATE(AfxGetStaticModuleState());
Teacher TeacherInst;
TeacherInst.pName = pTeaName;
TeacherInst.unNO = unTeaNO;
m_vTeacher.push_back(TeacherInst);
return S_OK;
}
//通过姓名工号
STDMETHODIMP CTeacher::GetTeaNOFromName(CHAR* pTeaName, ULONG* unTeaNO)
{
AFX_MANAGE_STATE(AfxGetStaticModuleState());
vector<Teacher>::iterator itTea;
for (itTea = m_vTeacher.begin(); itTea != m_vTeacher.end(); itTea++)
{
if (strcmp((*itTea).pName, pTeaName) == 0)
{
*unTeaNO = (*itTea).unNO;
break;
}
}
return S_OK;
}
//获取老师总数
STDMETHODIMP CTeacher::GetTeaNumber(UINT* punTeaNumber)
{
AFX_MANAGE_STATE(AfxGetStaticModuleState());
*punTeaNumber = m_vTeacher.size();
return S_OK;
}
5. 接口对外声明文件("VsAtlProjectOne.idl")添加以下代码:
// VsAtlProjectOne.idl : VsAtlProjectOne的 IDL 源
//
// 此文件将由 MIDL 工具处理以
// 产生类型库(VsAtlProjectOne.tlb)和封送处理代码。
import "oaidl.idl";
import "ocidl.idl";
[
object,
uuid(EA00B97F-C817-43B6-94A2-E3B52CAC9610),
dual,
nonextensible,
pointer_default(unique)
]
interface IStudent : IDispatch{
[id(1)] HRESULT AddStuInfo([in] CHAR* pStuName, [in] ULONG unStuNO, [in] UINT unStuAge, [in] CHAR* pStuAddress);
[id(2)] HRESULT GetStuAgeFromName([in] CHAR* pStuName, UINT* pStuAge);
[id(3)] HRESULT GetStuNOFromName([in] CHAR* pStuName, UINT* pnStuNO);
[id(4)] HRESULT GetStuAddressFromName([in] CHAR* pStuName, CHAR** pnStuAddress);
[id(5)] HRESULT GetStuNumber([out] UINT* punStuNumber);
};
[
object,
uuid(B6E8E710-37A4-49BD-9CD9-56313DF7AA59),
dual,
nonextensible,
pointer_default(unique)
]
interface ITeacher : IDispatch{
[id(1)] HRESULT AddTeacherInfo([in] CHAR* pTeaName, [in] UINT unTeaNO);
[id(2)] HRESULT GetTeaNOFromName([in] CHAR* pTeaName, [out] ULONG* unTeaNO);
[id(3)] HRESULT GetTeaNumber([out] UINT* punTeaNumber);
};
[
uuid(284DA5FE-71F9-4D34-8656-EF28201C766C),
version(1.0),
]
library VsAtlProjectOneLib
{
importlib("stdole2.tlb");
[
uuid(44DFFA13-CA7A-447C-960C-1676644028A0)
]
coclass Student
{
[default] interface IStudent;
};
[
uuid(8F193EA0-0E18-415D-9F46-DCF3D82D5E1F)
]
coclass Teacher
{
[default] interface ITeacher;
};
};
import "shobjidl.idl";
调用COM组件 ATL
#include "stdAfx.h"
#include "TestAtl.h"
//导入组件
//将"VsAtlProjectOne.dll" 放到目录 "C:\Windows\System32"
#import "VsAtlProjectOne.dll" no_namespace //如果不知道命名空间,需要加上 no_namespace
void TestAtl()
{
//初始化组件
::CoInitialize(NULL);
//获取组件接口的SID(通过属性)
CLSID sidStudent;
HRESULT hStudent = ::CLSIDFromProgID(L"VsAtlProjectOne.Student", &sidStudent);
if (hStudent == S_OK)
{
//获取接口对象(通过接口ID)
IStudent *pStudent(NULL);
hStudent = ::CoCreateInstance(sidStudent, NULL, CLSCTX_INPROC_SERVER, __uuidof(IStudent), (LPVOID *)&pStudent);
//调用接口函数(通过接口对象)
if (hStudent == S_OK)
{
hStudent = pStudent->AddStuInfo("赵四", 123456789, 88, "四川.长春");
if (hStudent == S_OK)
{
TRACE("\n查找学生成功\n");
}
else
{
TRACE("\n增加学生失败\n");
return;
}
hStudent = pStudent->AddStuInfo("刘能", 168, 18, "吉林.长春");
if (hStudent == S_OK)
{
TRACE("\n增加学生成功\n");
}
else
{
TRACE("\n增加学生失败\n");
return;
}
hStudent = pStudent->AddStuInfo("杨晓燕", 288, 28, "贵州.贵阳");
if (hStudent == S_OK)
{
TRACE("\n增加学生成功\n");
}
else
{
TRACE("\n增加学生失败\n");
return;
}
hStudent = pStudent->AddStuInfo("王大拿", 888, 99, "辽宁.大连");
if (hStudent == S_OK)
{
TRACE("\n增加学生成功\n");
}
else
{
TRACE("\n增加学生失败\n");
return;
}
hStudent = pStudent->AddStuInfo("谢广坤", 22222, 90, "辽宁.大连");
if (hStudent == S_OK)
{
TRACE("\n增加学生成功\n");
}
else
{
TRACE("\n增加学生失败\n");
return;
}
UINT unStuAge = 0;
hStudent = pStudent->GetStuAgeFromName("杨晓燕", &unStuAge);
if (hStudent == S_OK)
{
TRACE("\n查找学生成功\n");
}
else
{
TRACE("\n查找学生失败\n");
return;
}
UINT unStuNO = 0;
hStudent = pStudent->GetStuNOFromName("王大拿", &unStuNO);
if (hStudent == S_OK)
{
TRACE("\n查找学生成功\n");
}
else
{
TRACE("\n查找学生失败\n");
return;
}
CHAR *pStuAddress;
hStudent = pStudent->GetStuAddressFromName("刘能", &pStuAddress);
if (hStudent == S_OK)
{
TRACE("\n查找学生成功\n");
}
else
{
TRACE("\n查找学生失败\n");
return;
}
UINT unStuNumber(0);
hStudent = pStudent->GetStuNumber(&unStuNumber);
if (hStudent == S_OK)
{
TRACE("\n查找学生成功\n");
}
else
{
TRACE("\n查找学生失败\n");
return;
}
}
}
CLSID sidTeacher;
HRESULT hTeacher = ::CLSIDFromProgID(L"VsAtlProjectOne.Teacher", &sidTeacher);
if (hTeacher == S_OK)
{
ITeacher *pTeacher;
hTeacher = ::CoCreateInstance(sidTeacher, NULL, CLSCTX_INPROC_SERVER, __uuidof(ITeacher), (LPVOID *)&pTeacher);
if (hTeacher == S_OK)
{
hTeacher = pTeacher->AddTeacherInfo("严守一", 123456);
if (hTeacher == S_OK)
{
TRACE("\n添加老师成功\n");
}
else
{
TRACE("\n添加老师失败\n");
}
hTeacher = pTeacher->AddTeacherInfo("费默", 998);
if (hTeacher == S_OK)
{
TRACE("\n添加老师成功\n");
}
else
{
TRACE("\n添加老师失败\n");
}
hTeacher = pTeacher->AddTeacherInfo("于文娟", 1314);
if (hTeacher == S_OK)
{
TRACE("\n添加老师成功\n");
}
else
{
TRACE("\n添加老师失败\n");
}
ULONG unTeaNO(0);
hTeacher = pTeacher->GetTeaNOFromName("费默", &unTeaNO);
if (hTeacher == S_OK)
{
TRACE("\n查找老师成功\n");
}
else
{
TRACE("\n查找老师失败\n");
}
UINT unTeaNumber(0);
hStudent = pTeacher->GetTeaNumber(&unTeaNumber);
if (hStudent == S_OK)
{
TRACE("\n查找老师成功\n");
}
else
{
TRACE("\n查找老师失败\n");
return;
}
}
}
//释放线程加载的组件,卸载线程所有的DLL
::CoUninitialize();
}