Delphi7中的宽字符串到字符串的转换
我的应用程序是用Delphi7编写的非unicode应用程序 我想使用此函数将unicode字符串转换为ANSI:Delphi7中的宽字符串到字符串的转换,delphi,unicode,localization,delphi-7,ansi,Delphi,Unicode,Localization,Delphi 7,Ansi,我的应用程序是用Delphi7编写的非unicode应用程序 我想使用此函数将unicode字符串转换为ANSI: function convertU(ws : widestring) : string; begin result := string(ws); end; 我还使用此代码设置要转换的正确代码页 initialization SetThreadLocale(GetSystemDefaultLCID); GetFormatSettings; 它在VCL主线程中工作得很好
function convertU(ws : widestring) : string;
begin
result := string(ws);
end;
我还使用此代码设置要转换的正确代码页
initialization
SetThreadLocale(GetSystemDefaultLCID);
GetFormatSettings;
它在VCL主线程中工作得很好,但在TThread中却不行,
在这里,我得到了一些问题标记“?”,这是函数convertU的结果
为什么不在TThread中?在
初始化
块中调用SetThreadLocale()
对TThread
没有影响。如果要设置线程的区域设置,必须在TThread.Execute()
方法内部调用SetThreadLocale()
更好的选择是根本不依赖
SetThreadLocale()
。通过直接调用WideCharToMultiByte()
进行您自己的转换,这样您就可以指定要转换到的特定Ansi代码页。AFAIKSetThreadLocale
不会更改当前的系统代码页,因此不会影响Delphi 7中的widestring
到转换,它依赖于GetACP
API调用,即系统代码页
例如,在Windows 7中,在控制面板中设置系统代码页,然后在非Unicode应用程序中设置区域语言/管理选项卡/代码页。这需要重新启动系统
Delphi7使用此系统代码页,为所有转换API调用提供0。因此,在Delphi7中,AFAIRSetThreadLocale
不会影响widestring
到ansisting
的转换。它将更改区域设置(例如日期/时间和货币格式),而不是系统用于Ansi Unicode转换的代码页
较新版本的Delphi有一个setMultibyteConversionDepage()
函数,可以设置用于所有ansisting
处理的代码页
但是API调用(即Windows.pas中所有由Delphi 7中的..()
映射的..A()
函数)将使用此系统代码页。因此,如果要处理另一个代码页,则必须在转换为Unicode后调用…W()
宽API。也就是说,Delphi 7 VCL将仅与系统代码页一起工作,而不是由SetThreadLocale
指定的值
根据Delphi 7,我的建议是:
- 在任何地方使用
WideString
和特定的“Wide”API调用-Delphi 7有多组组件处理WideString
李>
- 使用您自己的类型,使用专用的字符集,但在使用VCL/RTL或“Ansi”API调用之前,您需要进行显式转换-例如
MyString=type AnsiString
(这是我们在mORMot中所做的,通过为内部UTF-8进程定义自定义RawUTF8
类型)
这在Delphi 2009及更高版本中处理得更好,因为您可以为每个解析类型指定一个代码页,并正确处理API调用或VCL进程与Unicode之间的转换;一个简单的stringVar:=wideStringVar代码>将起作用。第二,问题是并非所有WideChar都可以直接转换为AnsiString;有些字体的宽度不止一个字符,有些字体的字符值在AnsiChar中无法表示,有些字体不包含所有可能的Unicode值。如果您看到的是?
,这意味着您正在显示它们,这可能是第三个问题-线程不应在不使用同步化的情况下访问GUI控件。因为您没有发布显示代码,所以很难说是否是这样。问题是:为什么在TThread中使用时会出现问号?我重复一遍:如果您看到?
,则显示文本。您提供了零代码或有关如何显示它的信息。我使用Debugger查看返回值是否为系统默认LCID的TThread感知?如果您是应用程序中所有代码的作者,则显式调用WideChartMultiByte是可行的选项。如果包含第三方代码,则区域设置的线程范围设置可能是最佳折衷方案。是。谢谢我现在混合使用这两种方法:WideCharToMultiByte和SetThreadLocale(),因为我首先开始使用WideCharToMultiByte,但我认为我将删除对该函数的调用,并且只对每个线程使用SetThreadLocale。AFAIKSetThreadLocale
不会更改当前的系统代码页,因此不会影响Delphi7中widestring到ansistring的转换,它依赖于GetACP
API调用。我只想处理默认的系统代码页。我注意到,对于UnicodeAnsi转换,使用的代码页是默认用户LCID,而不是默认系统LCID,这是一个问题。