一、IDispatch接口与Variant类型
1.IDispatch的简介与作用
a) 自动化技术让解释下语音能够调用到自定义的接口,
b) 具有自动化功能的组件是支持IDispatch接口的COM组件
c) IDispatch能够接收一个函数的字符串名称,并执行这个函数.
d) 解释性语言要调用COM组件的自定义接口都是通过自动化控制
程序把自定义接口中的函数的字符串和参数传递给IDispatch
而IDispatch间接的执行自定义接口中的函数.
e) 重要的函数 GetIDsOfNames和Invoke
GetIDsOfNames函数将读取一个函数名称,并返回其调用ID,
Invoke函数接收一个调度ID,跟函数参数,执行调用ID所对应函数功能.
f) 所以解释下语音跟宏语音不必直接认识我们的自定义接口,
只要我们的COM组件支持了IDispatch接口,他们就能通过自动化控制
程序调用我们的IDispatch接口,通过传入函数名字的字符串
和函数参数来执行调用我们的自定义接口.
2.常用的COM数据类型
a)基本类型
CHAR typedef char CHAR CHAR* char指针
BYTE 无符号的char BYTE*
SHORT typedef short SHORT SHORT*
USHORT 无符号short USHORT*
INT typedef int INT*
UINT 无符号int UINT*
LONG typedef long LONG*
ULONG 无符号long ULONG*
FLOAT FLOAT*
DOUBLE DOUBLE*
VARIANT_BOOL COM中的布尔类型 typedef short VARIANT_BOOL
注意: 0== FALSE -1== TRUE
VARIANT_BOOL*
b) 字符串
BSTR COM中的字符串类型
BSTR* BSTR指针
BSTR是指向的是宽字符串的指针,是一个带有
字符计数值的字符串,且这个计数值是保存在字符数组的开头
3.BSTR基本操作
a) 错误赋值 BSTR str = L"ABCD";
这样是错误的,因为字符串前面没有计数值
b)BSTR SysAllocString(const OLECHAR*)
是COM申请BSTR字符串的方法,把CHAR* 传进去,返回BSTR类型
c)BSTR SysAllocStringLen(const OLECHAR* ,UINT)
根据字符串指针与字符个数构造BSTR字符串
d)UINT SysStringLen(BSTR)获取字符串计数值
e)void SysFreeString(BSTR)释放字符串,当COM中的
字符串(BSTR)不再使用后,调用该函数.
BSTR strA = SysAllocString(L"Hello"); //申请一个字符串
//申请指定个数字符串,从参数1中取
BSTR strB = SysAllocStringLen(strA,SysStringLen(strA));
SysFreeString(strA);
SysFreeString(strB);
4.COM常用数据类型
IUnknown* COM的最基本的接口指针
IUnknown** 指针的指针
IDispatch* 支持组件自动化的接口
IDispatch** IDispatch*的指针
如果写的组件不想被 解释性的语言 脚本语言
查找接口的话, 可以直接使用IUnknown接口
5.万能数据类型 VARIANT
a) 具备跨语言的特性,同时能存储任何的数据类型
为了实现这个类型的功能,C++中这个类型是一个结构体,
这个结构体,里面又有联合体,联合多种基本数据类型
又有变量类型标志VARTYPE vt.标志他的类型
b) 初始化和清楚
VARIANT var; VariantInit(&var); //此时var.vt == VT_EMPTY控件 //..其他操作 //清除操作 VariantClear(&var);
c) VARIANT的使用
用VARIANT保存LONG类型
VARIANT var; VariantInit(&var); //此时var.vt == VT_EMPTY控件 //..其他操作 //清除操作 //VT_I4 ×××就是VT_I2 var.vt = VT_I4; //赋值 var.lVal = 100; VariantClear(&var);
FLOAT类型 VT_R4 DOUBLE VT_R8
var.fltVal flaot值
VARIANT使用BSTR类型
var.vt = VT_BSTR;
var.bstrVal = SysAllocString(L"HEllo");
VT_BOOL 布尔类型
d) 读取值
//先判断类型 在根据类型读取
if(var.vt == VT_l4)
{
LONG lValue = var.lVar;
}
6.COM数据类型的转换
LONG转换成FLOAT
VARIANT var; 初始化
var.vt = VT_I4;
var.lVar = 100;
VariantChangeType(&var,&var,0,VT_R4);
if(var.vt = VT_R4)
{
LONG fValue = var.fltValue;
}
清空var
7.VARIANT类型的派生类
a) 在派生类扩展VARIANT类使得他的使用更加方便
#include <atlbase.h>ATL库里面就带有一个派生类CComVariant
他简化了初始化和清楚, 构造函数可以直接传递基本类型或者VARIANT类型
可以用C++的类型,也可以用COM基本类型来构造一个对象
INT a = 10; CComVariant b(a); double c = 100.0100; CComVariant d(c);
b) 赋值 重载了运算符 operator= 根据不同类型分配不同值
也就是说如果你是INT型 直接对象=值 d = 100;
(二)、测试简单对象
一、ATL制作简单对象(Simple Object)
完成即可
1.项目创建完成,添加简单对象(Simple Object)
选择简单对象
输入简称
ProgId
ATLProject.HelloSimpleObject
ProgID是程序员给某个CLSID指定一个程序员易记的名称,
某些计算机语言通过PropID来标记组件 命名规则
<Program>.<Component>.<Version>
程序.组件.版本
双重是支持IDispatch接口的,这样这个接口就会支持一些脚本语言等等。
2.给简单对象添加一个方法,
在类视图选中刚添加的这个(选中接口不是添加的类)然后添加方法
接口方法是固定的HRESULT,所以只能用输入的参数作为返回值.
in代表输入
加一个指针就可以显示out,表示是输出的可作为返回值
retval表示用他做返回值
这个ID表示这个方法 在接口里的ID,直接点击完成即可
3.来到解决方案管理器查看项目ild文件
ATLProjectLib的uuid
组件的UUID他被ATLProjectLib包含,组件又包含了这个 我们自定义的接口
会发现我们的组件(简单对象就是组件)支持我们自定义接口(IHelloSimpleObject)
接口定义上面会看到接口IID,
而且接口里就有一个我们刚创建的方法, 他的ID是1
4.方法的声明和实现
在.h文件里声明了
在.c文件里实现了
5.添加属性
他会自动给这个属性添加 SET和GET方法,
ProPutRef表示为引用参数
添加属性方法ID自增
6.编译生成
除了dll文件还生成了两个代码文件(ATLProject_i.h和 _i.c)
这两个文件里面描述的是组件的相关信息,如接口方法接口iid,组件CLSID
7.组件的CLSID
组件的CLSID和IID一样,都是GUID,
组件的CLSID用于标识组件,每一个组件都有一个与之对应的CLSID
红色就是组件名,上面就是他的CLSID
这个就是你输入的组件名
二、在MFC中测试简单对象
直接创建一个对话框程序
stdafx.h添加 _i.h文件 stdafx.cpp 添加_h.c文件
测试代码
组件这些都被宏定义了,使用更方便
HRESULT hr = E_FAIL; //使用COM组件必须初始化 hr = CoInitialize(NULL); if(SUCCEEDED(hr)) { //接口指针对象 IHelloSimpleObject* pHello = NULL; //创建接口指针实例 组件对象 //第一个参数是组件标识 //第二个参数NULL //第三个参数一般用这个CLSCTX_INPROC_SERVER //第四个参数接口标识符 //第五个参数 接口指针 返回 hr = CoCreateInstance(CLSID_HelloSimpleObject,NULL,CLSCTX_INPROC_SERVER, IID_IHelloSimpleObject,(LPVOID*)&pHello); if(SUCCEEDED(hr)) { LONG sum = 0; hr = pHello->SumLong(100,100,&sum); //读取描述 BSTR bstrs = SysAllocString(L""); hr = pHello->get_m_desc(&bstrs); SysAllocString(bstrs); bstrs = NULL; //写入 BSTR strb = SysAllocString(L"MFC中测试"); hr = pHello->put_m_desc(strb); SysAllocString(strb); bstrs = NULL; bstrs = SysAllocString(L""); hr = pHello->get_m_desc(&bstrs); SysAllocString(bstrs); bstrs = NULL; } //接口不再使用 pHello->Release(); } //不再使用com组件对象时 一般放在程序结束 CoUninitialize();