在Delphi 7中进行字符串转换

use*_*591 6 delphi unicode localization ansi delphi-7

我的应用程序是一个用Delphi 7编写的非unicode应用程序.

我想用这个函数将unicode字符串转换为ANSI:

function convertU(ws : widestring) : string;
begin
  result := string(ws);
end;
Run Code Online (Sandbox Code Playgroud)

我还使用此代码来设置要转换的正确代码页.

initialization
  SetThreadLocale(GetSystemDefaultLCID);
  GetFormatSettings;
Run Code Online (Sandbox Code Playgroud)

它在VCL主线程中工作得很好,但在TThread中却没有,在那里我得到一些问题标记'?' 作为函数convertU的结果.

为什么不在TThread?

Arn*_*hez 6

AFAIK SetThreadLocale不改变当前系统代码页,所以不会影响widestringansistring转换在Delphi 7,依靠GetACPAPI调用,即该系统的代码页.

例如,在控制面板中的Windows 7中设置系统代码页,然后在非Unicode应用程序中设置区域语言/管理选项卡/代码页.这需要重启系统.

Delphi 7使用此系统代码页,为所有转换API调用提供0.所以AFAIR SetThreadLocale不会影响widestringansistring转换在Delphi 7.都会改变本地化(例如日期/时间和货币格式),而不是由系统以其安西使用的代码页< - > Unicode转换.

较新版本的Delphi具有一个SetMultiByteConversionCodePage()功能,能够设置用于所有AnsiString处理的代码页.

但API调用(即....A()Windows.pas中由...()Delphi 7 映射的所有函数)将使用此系统代码页.因此...W(),如果要处理另一个代码页,则必须在转换为Unicode后调用宽API.也就是说,Delphi 7 VCL仅适用于系统代码页,而不是指定的值SetThreadLocale.

根据Delphi 7,我的建议是:

  • WideString在任何地方使用,以及特定的"宽"API调用 - Delphi 7有几组处理组件WideString;
  • 使用您自己的类型,使用专用的字符集,但在使用VCL/RTL或"Ansi"API调用之前,您需要进行显式转换 - 例如MyString = type AnsiString(这是我们在mORMot中所做的,通过RawUTF8为内部UTF 定义自定义类型 - 8过程).

使用Delphi 2009可以更好地处理这个问题,因为您可以为每种AnsiString类型指定代码页,并正确处理与Unicode之间的转换,以及API调用或VCL进程.


Rem*_*eau 5

调用SetThreadLocale()一个内部initialization块有没有影响TThread.如果要设置线程的语言环境,则必须SetThreadLocale()TThread.Execute()方法内部调用.

更好的选择是完全不依赖SetThreadLocale().通过WideCharToMultiByte()直接调用进行自己的转换,以便指定要转换为的特定Ansi代码页.