Chinaunix首页 | 论坛 | 博客
  • 博客访问: 18689375
  • 博文数量: 7460
  • 博客积分: 10434
  • 博客等级: 上将
  • 技术积分: 78178
  • 用 户 组: 普通用户
  • 注册时间: 2008-03-02 22:54
文章分类

全部博文(7460)

文章存档

2011年(1)

2009年(669)

2008年(6790)

分类: C/C++

2008-05-31 09:05:17

由于 BSTR 是记数 Unicode 字符串,你可以用标准转换方法来创建 8 位的 CString。实际上,这是 CString 内建的功能。在 CString 中 有特殊的构造函数可以把 ANSI 转化成 Unicode,也可以把Unicode 转化成 ANSI。你同样可以从 VARIANT 类型的变量中获得 BSTR 类型的字符串,VARIANT 类型是 由各种 COM 和 Automation (自动化)调用返回的类型。

例如,在一个ANSI程序中:
BSTR b;
b = ...; // whatever
CString s(b == NULL ? L\"\" : b)

  对于单个的 BSTR 串来说,这种用法可以工作得很好,这是因为 CString 有一个特殊的构造函数以LPCWSTR(BSTR正是这种类型)为参数,并将它转化成 ANSI 类型。专门检查是必须的,因为 BSTR 可能为空值,而 CString 的构造函数对于 NULL 值情况考虑的不是很周到,(感谢 Brian Ross 指出这一点!)。这种用法也只能处理包含 NUL 终结字符的单字符串;如果要转化含有多个 NULL 字符 串,你得额外做一些工作才行。在 CString 中内嵌的 NULL 字符通常表现不尽如人意,应该尽量避免。
  根据 C/C++ 规则,如果你有一个 LPWSTR,那么它别无选择,只能和 LPCWSTR 参数匹配。

在 Unicode 模式下,它的构造函数是:

CString::CString(LPCTSTR);

正如上面所表示的,在 ANSI 模式下,它有一个特殊的构造函数:

CString::CString(LPCWSTR); 

  它会调用一个内部的函数将 Unicode 字符串转换成 ANSI 字符串。(在Unicode模式下,有一个专门的构造函数,该函数有一个参数是LPCSTR类型——一个8位 ANSI 字符串指针,该函数将它加宽为 Unicode 的字符串!)再次强调:一定要检查 BSTR 的值是否为 NULL。
  另外还有一个问题,正如上文提到的:BSTRs可以含有多个内嵌的NULL字符,但是 CString 的构造函数只能处理某个串中单个 NULL 字符。也就是说,如果串中含有嵌入的 NUL字节,CString 将会计算出错误的串长度。你必须自己处理它。如果你看看 strcore.cpp 中的构造函数,你会发现 它们都调用了lstrlen,也就是计算字符串的长度。
  注意从 Unicode 到 ANSI 的转换使用带专门参数的 ::WideCharToMultiByte,如果你不想使用这种默认的转换方式,则必须编写自己的转化代码。
  如果你在 UNICODE 模式下编译代码,你可以简单地写成:

CString convert(BSTR b)
{
if(b == NULL)
return CString(_T(\"\"));
CString s(b); // in UNICODE mode
return s;
}

  如果是 ANSI 模式,则需要更复杂的过程来转换。注意这个代码使用与 ::WideCharToMultiByte 相同的参数值。所以你 只能在想要改变这些参数进行转换时使用该技术。例如,指定不同的默认字符,不同的标志集等。
CString convert(BSTR b)
{
CString s;
if(b == NULL)
return s; // empty for NULL BSTR
#ifdef UNICODE
s = b;
#else
LPSTR p = s.GetBuffer(SysStringLen(b) + 1);
::WideCharToMultiByte(CP_ACP, // ANSI Code Page
0, // no flags
b, // source widechar string
-1, // assume NUL-terminated
p, // target buffer
SysStringLen(b)+1, // target buffer length
NULL, // use system default char
NULL); // don\'\'t care if default used[Page]
s.ReleaseBuffer();
#endif
return s;
}
  我并不担心如果 BSTR 包含没有映射到 8 位字符集的 Unicode 字符时会发生什么,因为我指定了::WideCharToMultiByte 的最后两个参数为 NULL。这就是你可能需要改变的地方。
阅读(739) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~