6

我的应用程序是用 Delphi 7 编写的非 unicode 应用程序。

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

function convertU(ws : widestring) : string;
begin
  result := string(ws);
end;

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

initialization
  SetThreadLocale(GetSystemDefaultLCID);
  GetFormatSettings;

它在 VCL 主线程中效果很好,但在 TThread 中效果不佳,在那里我得到了一些问号“?” 作为函数convertU的结果。

为什么不在 TThread 中?

4

2 回答 2

6

AFAIKSetThreadLocale不会改变当前系统Code Page,所以不会影响Delphi 7中依赖API调用的widestringto转换,即系统Code Page。ansistringGetACP

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

Delphi 7 使用这个系统代码页,为所有转换 API 调用提供 0。所以 AFAIRSetThreadLocale不会影响 Delphi 7 中的widestringtoansistring转换。它会改变语言环境(例如日期/时间和货币格式),而不是系统用于其 Ansi <-> Unicode 转换的代码页。

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

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

在 Delphi 7 下,我的建议是:

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

This is much better handled with Delphi 2009 and up, since you can specify a code page to every AnsiString type, and properly handle conversion to/from Unicode, for API calls or VCL process.

于 2012-09-09T12:15:41.920 回答
5

SetThreadLocale()在块内调用initializationTThread. 如果要设置线程的语言环境,则必须SetThreadLocale()在方法内部调用TThread.Execute()

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

于 2012-09-09T07:31:17.703 回答