BASIC 中字符串类型的表示方式---BSTR,BSTR 其实是一个指针类型,
BSTR是一个指向UNICODE字符串的指针,其向前的4个字节中保存了该字符串的字节长度(不包含结束符),该字符串占用了16个字节。如此,分布式应用中就能把该指针传送到远端的计算机上了。(指针 + 内存长度)
有关 BSTR 的处理函数:
 
API 函数 说明
SysAllocString() 申请一个 BSTR 指针,并初始化为一个字符串
SysFreeString() 释放 BSTR 内存
SysAllocStringLen() 申请一个指定字符长度的 BSTR 指针,并初始化为一个字符串
SysAllocStringByteLen() 申请一个指定字节长度的 BSTR 指针,并初始化为一个字符串
SysReAllocStringLen() 重新申请 BSTR 指针

CString 函数

说明

AllocSysString() 从 CString 得到 BSTR
SetSysString() 重新申请 BSTR 指针,并复制到 CString 中

CComBSTR 函数

ATL 的 BSTR 包装类。在 atlbase.h 中定义

Append()、AppendBSTR()、AppendBytes()、ArrayToBSTR()、BSTRToArray()、AssignBSTR()、Attach()、Detach()、Copy()、CopyTo()、Empty()、Length()、ByteLength()、ReadFromStream()、WriteToStream()、LoadString()、ToLower()、ToUpper()
运算符重载:!,!=,==,<,>,&,+=,+,=,BSTR
    太多了,但从函数名称不能看出其基本功能。详细资料,查看MSDN 吧。另外,左侧函数,有很多是 ATL 7.0 提供的,VC6.0 下所带的 ATL 3.0 不支持。
    由于我们将来主要用 ATL 开发组件程序,因此使用 ATL 的 CComBSTR 为主。VC也提供了其它的包装类 _bstr_t。
 字符串之间的相互转换函数:
WideCharToMultiByte(),
MultiByteToWideChar(),
ATL 提供的转换宏(USES_CONVERSION;  // 只需要调用一次,就可以在函数中进行多次转换)
A2BSTR OLE2A T2A W2A
A2COLE OLE2BSTR T2BSTR W2BSTR
A2CT OLE2CA T2CA W2CA
A2CW OLE2CT T2COLE W2COLE
A2OLE OLE2CW T2CW W2CT
A2T OLE2T T2OLE W2OLE
A2W OLE2W T2W W2T
六、VARIANT
  C++、BASIC、Java、Pascal、Script......计算机语言多种多样,而它们各自又都有自己的数据类型,COM 产生目的,其中之一就是要跨语言(注3)。而 VARIANT 数据类型就具有跨语言的特性,同时它可以表示(存储)任意类型的数据。从C语言的角度来讲,VARIANT 其实是一个结构,结构中用一个域(vt)表示------该变量到底表示的是什么类型数据,同时真正的数据则存贮在 union 空间中。结构的定义太长了(虽然长,但其实很简单)大家去看 MSDN 的描述吧,这里给出如何使用的简单示例:

学生:我想用 VARIANT 表示一个4字节长的整数,如何做?
老师:VARIANT v; v.vt=VT_I4; v.lVal=100;

学生:我想用 VARIANT 表示布尔值“真”,如何做?
老师:VARIANT v; v.vt=VT_BOOL; v.boolVal=VARIANT_TRUE;
学生:这么麻烦?我能不能 v.boolVal=true; 这样写?
老师:不可以!因为
 
类型 字节长度 假值 真值
bool 1(char) 0(false) 1(true)
BOOL 4(int) 0(FALSE) 1(TRUE)
VT_BOOL 2(short int) 0(VARIANT_FALSE) -1(VARIANT_TRUE)

  所以如果你 v.boolVal=true 这样赋值,那么将来 if(VARIANT_TRUE==v.boolVal) 的时候会出问题(-1 != 1)。但是你注意观察,任何布尔类型的“假”都是0,因此作为一个好习惯,在做布尔判断的时候,不要和“真值”相比较,而要与“假值”做比较。
学生:谢谢老师,你太牛了。我对老师的敬仰如滔滔江水,连绵不绝......

学生:我想用 VARIANT 保存字符串,如何做?
老师:VARIANT v; v.vt=VT_BSTR; v.bstrVal=SysAllocString(L"Hello,你好");

学生:哦......我明白了。可是这么操作真够麻烦的,有没有简单一些的方法?
老师:有呀,你可以使用现成的包装类 CComVariant、COleVariant、_variant_t。比如上面三个问题就可以这样书写:CComVariant v1(100),v2(true),v3("Hello,你好"); 简单了吧?!(注4)

学生:老师,我再问最后一个问题,我如何用 VARIANT 保存一个数组?
老师:这个问题很复杂,我现在不能告诉你,我现在告诉你怕你印象不深......(注5)
学生:~!@#$%^&*()......晕!

 
COM学习精彩文章
 
COM学习整理
如何使用第三方COM组件?已经有了第三方的COM组件(如OCX,DLL,TLB),该如何使用呢?
最简单的方法就是:
1.了解组件,详细了解组件包含什么样的接口和方法;
建议使用OleView.exe程序来详细了解组件包含什么样的接口和方法。找不到,Dcomcnfg.exe也行。

引入接口
通过#import指令引入接口,例如:
#import “ABCDEFG.DLL” named_guids raw_interfaces_only no_namespace

2.初始化
调用CoInitialize()或CoInitlaizeEx()来初始化COM运行环境,例如:
 CoInitialize(0);

获取接口
根据第一步了解的知识,在初始化环境后,可以获取接口了,例如:
 IMyObject* obj = NULL; // 假定接口是IMyObject

// 返回值为HRESULT类型的,典型地,S_OK(0)表示成功,E_FAIL表示失败,还有其它的失败值
HRESULT hr = CoCreateInstance(__uuidof(MyObject), NULL, CLSCTX_ALL, __uuidof(IMyObject), (void **)&obj);

if ( SUCCEEDED(hr) ) // 或者 if ( !FAILEd(hr) )
{
  …..利用接口作些事
  //最后释放接口
  IMyObject->Release();
}

3.方法调用
根据第一步了解的知识,调用接口的方法做某些事,例如:
HRESULT hr= obj->Method(arg1, arg2); // 方法都返回HRESULT类型的值

if ( SUCCEEDED(hr) )
{
  // 调用成功,作其它事
}
注意事项
使用COM组件,特别注意方法的参数类型,如BSTR,SAFEARRAY,VARIANT之类 ,如果有用到这些类型,请仔细参阅有关这些类型说明的资料。
4.结束
接口使用结束后,需要释放COM环境,如下:
CoUninitialize(); 

 
*********************
问答时间:1