本文参考自 RAD Studio 2009 联机帮助
随着 Embarcadero 8 月 25 号发布 RAD Studio 2009 (Tiburon) 以来(Tiburon 的 RTM 日期可能要延后到 9 - 10 月),随着 Tiburon 全面支持 Unicode,现有的 Delphi / C++ Builder 项目要迁移到 Unicode 下应该注意些什么也成为大家最为关心的问题。Tiburon 对 Unicode 的支持不仅仅是将原来 类型映射为 AnsiString 的 String 类型直接改成 WideString,而是对 AnsiString 结构作出修改,同时增加了 UnicodeString 类型来完美支持 Unicode。这意味着,要想平稳迁移到 Unicode 下,程序员不得不对现有代码作出一定的修改。
在 Tiburon 以前的版本中,AnsiString 和 WideString 除了 data size 不同外,在功能上是相同的。早先版本的 AnsiString 的结构如下:
而这个结构在 Tiburon 中已经发生变化,AnsiString 增加了两个新的 fields, 一个是 CodePage,一个是 ElemSize,这样做可以让新版的 AnsiString 和 UnicodeString 在结构上保持一致。
而 WideString 类型在早先的版本中用来保存双字节数据。其本质和 Windows BSTR 是一样的。在 Tiburon 中 WideString 仍然是为 COM 保持兼容的,也就是说它依然没有引用计数,相比较而言,UnicodeString 在性能和效率上将会是 COM 以外的程序首选的字符类型。
闪亮登场的 UnicodeString 类型
Tiburon 中,新的、默认的 string 就是 UnicodeString。这个类型既可以包含 ANSI 字符,也可以包含 Unicode 字符。下面是 UnicodeString 类型的结构:
UnicodeString 和 AnsiString 都是如上的结构,尽管 UnicodeString 包含是双字节数据,AnsiString 包含的是单字节的。
用 Object Pascal 语言来描述 UnicodeString 的结构,应该是这样:
type
StrRec = record
CodePage: Word;
ElemSize: Word;
refCount: Integer;
Len: Integer;
case Integer of
1: array[0..0] of AnsiChar;
2: array[0..0] of WideChar;
end;
UnicodeString 增加了 code page 字段和 element size 来描述字符串内容,这使得 UnicodeString 和其它类型的字符串可以很好的相兼容,所以 AnsiString 和 UnicodeString 可以很方便的互相转换,唯一要注意的是,当把 UnicodeString 向下转型到 AnsiString 的时候,可能会丢失数据,因此强烈建议你不要这么做。UnicodeString 保存的是 UTF-16 字符。
在旧的环境下,可以使用编译标志 Unicode 来判断编译环境是否支持 UnicodeString,以便您可以在同一套代码中维护不同版本的字符支持环境。编译指令如下:
Delphi 使用:
{$IFDEF
Unicode}
C++ Builder 使用:
#ifdef _DELPHI_STRING_UNICODE
变化概要:
下面的操作将不再依赖字符 Size:
随着 Embarcadero 8 月 25 号发布 RAD Studio 2009 (Tiburon) 以来(Tiburon 的 RTM 日期可能要延后到 9 - 10 月),随着 Tiburon 全面支持 Unicode,现有的 Delphi / C++ Builder 项目要迁移到 Unicode 下应该注意些什么也成为大家最为关心的问题。Tiburon 对 Unicode 的支持不仅仅是将原来 类型映射为 AnsiString 的 String 类型直接改成 WideString,而是对 AnsiString 结构作出修改,同时增加了 UnicodeString 类型来完美支持 Unicode。这意味着,要想平稳迁移到 Unicode 下,程序员不得不对现有代码作出一定的修改。
在 Tiburon 以前的版本中,AnsiString 和 WideString 除了 data size 不同外,在功能上是相同的。早先版本的 AnsiString 的结构如下:
Format of AnsiString Data
Type
Reference Count
|
Length
|
String Data (Byte sized)
|
Null Term
|
-8
|
-4
|
0
|
Length
|
而这个结构在 Tiburon 中已经发生变化,AnsiString 增加了两个新的 fields, 一个是 CodePage,一个是 ElemSize,这样做可以让新版的 AnsiString 和 UnicodeString 在结构上保持一致。
而 WideString 类型在早先的版本中用来保存双字节数据。其本质和 Windows BSTR 是一样的。在 Tiburon 中 WideString 仍然是为 COM 保持兼容的,也就是说它依然没有引用计数,相比较而言,UnicodeString 在性能和效率上将会是 COM 以外的程序首选的字符类型。
闪亮登场的 UnicodeString 类型
Tiburon 中,新的、默认的 string 就是 UnicodeString。这个类型既可以包含 ANSI 字符,也可以包含 Unicode 字符。下面是 UnicodeString 类型的结构:
Format of UnicodeString Data
Type
CodePage
|
Element Size
|
Reference Count
|
Length
|
String Data (element sized)
|
Null Term
|
-12
|
-10
|
-8
|
-4
|
0
|
Length * elementsize
|
UnicodeString 和 AnsiString 都是如上的结构,尽管 UnicodeString 包含是双字节数据,AnsiString 包含的是单字节的。
用 Object Pascal 语言来描述 UnicodeString 的结构,应该是这样:
type
UnicodeString 增加了 code page 字段和 element size 来描述字符串内容,这使得 UnicodeString 和其它类型的字符串可以很好的相兼容,所以 AnsiString 和 UnicodeString 可以很方便的互相转换,唯一要注意的是,当把 UnicodeString 向下转型到 AnsiString 的时候,可能会丢失数据,因此强烈建议你不要这么做。UnicodeString 保存的是 UTF-16 字符。
在旧的环境下,可以使用编译标志 Unicode 来判断编译环境是否支持 UnicodeString,以便您可以在同一套代码中维护不同版本的字符支持环境。编译指令如下:
Delphi 使用:
C++ Builder 使用:
变化概要:
- String 类型映射为 UnicodeString 而不是 AnsiString
- Char 类型映射为 WideChar(2 bytes not 1 byte), 并且是 UTF-16 字符
- PChar 类型映射为 PWideChar
- C++ 中,System::String 映射到 UnicodeString 类
- Delphi 中,AnsiString 映射为早先版本中默认的 string
- AnsiString
- WideString
- AnsiChar
- PAnsiChar
- 隐式转换仍然可用
- 用户的活动页代码(The user's active code page)控制着模式(ANSI vs. Unicode),所以 AnsiString 仍然可以支持
下面的操作将不再依赖字符 Size:
- 合并字符串
-
- <string var> + <string var>
- <string var> + <literal>
- <literal> + <literal>
- Concat(<string> , <string>)
- 标准字符串函数
-
- Length(<string>)返回字符元素的长度,此值可能和字符在字节长度上并不匹配。SizeOf 函数则返回数据的字节长度,这意味着 SizeOf 和 Length 的返回值可能是不同的
- Copy(<string>, <start>, <length>)返回的 SubString 基于字符元素
- Pos(<substr>,<string>)返回第一个字符元素的序号
- 操作
-
- <string> <comparison op> <string>
- CompareStr()
- CompareText()
- ...
- FillChar(<struct or memory>)
-
- FillChar(Rect, SizeOf(Rect), #0)
- FillChar(WndClassEx, SizeOf(TWndClassEx), #0). 使用的时候注意 WndClassEx.cbSize := SizeOf(TWndClassEx)
- Windows API
-
- API 默认使用 WideString (*W)形态的版本
- PChar(<string>)具有相同的语义
GetModuleFileName:
function ModuleFileName(Handle: HMODULE): string;
var
Buffer: array[0..MAX_PATH] of Char;
begin
SetString(Result, Buffer,
GetModuleFileName(Handle, Buffer, Length(Buffer)));
end;
GetWindowText:
function WindowCaption(Handle: HWND): string;
begin
SetLength(Result, 1024);
SetLength(Result, GetWindowText(Handle,
PChar(Result), Length(Result)));
end;
字符串索引:
function StripHotKeys(const S: string): string;
var
I, J: Integer;
LastChar: Char;
begin
SetLength(Result, Length(S));
J := 0;
LastChar := #0;
for I := 1 to Length(S) do
begin
if (S[I]
<> '&') or (LastChar
= '&') then
begin
Inc(J);
Result[J] := S[I];
end;
LastChar :=
S[I];
end;
SetLength(Result, J);
end;
(未完,待续)function ModuleFileName(Handle: HMODULE): string;
var
begin
end;
function WindowCaption(Handle: HWND): string;
begin
end;
字符串索引:
function StripHotKeys(const S: string): string;
var
begin
end;