Delphi 7 - 为什么Windows 7会在运行时更改字符编码?

时间:2010-03-31 08:08:20

标签: delphi encoding windows-7 delphi-7

我有一个delphi 7表单:

Form http://i44.tinypic.com/13ymott.jpg

和我的代码:

Code http://i44.tinypic.com/x1gh9c.jpg

当我在Windows 7中运行此表单时,我看到:

Windows7Form http://i41.tinypic.com/riglzl.jpg

在设计时,表单在第一个标签中有抛光字母,但在运行时没有它们。它在Vista或Windows XP上看起来不错。当我在代码中设置第二个标签的标题时,一切正常并且字符被正确编码。

Windows 7上的顶级标签的前5个代码:65 97 69 101 83

Windows Vista / XP上的顶级标签的前5个代码:165 185 202 234 140

每个系统的底部标签的前5个代码:165 185 202 234 140

Windows 7更改编码,为什么?我的系统设置似乎没问题。我在控制面板中为非unicode应用程序设置了适当的语言。

修改

此问题不仅与表单上的标签有关,还与FastReport(切换到EASTERN_CHARSET解决问题)或通过COM接口访问Microsoft Excel有关。

4 个答案:

答案 0 :(得分:2)

我确实在win XP中重现了Delphi 2010中的行为。

procedure Button1Click(Sender : TObject);
begin
  ShowMessage(AnsiString(Label1.Caption));
end;

在这种情况下,Label1.Caption到AnsiString的转换是通过WideCharToMultiByte完成的(Windows API)。

API有以下注释:

  

ANSI代码页可以不同   在不同的计算机上,或者可以   改为一台电脑,领先   数据损坏。最多的   一致的结果,应用   应该使用Unicode,例如UTF-8或   UTF-16,而不是特定的代码   页面,除非传统标准或数据   格式阻止使用Unicode。如果   使用Unicode是不可能的,   应用程序应标记数据   使用适当的编码流   协议允许的名称。 HTML和   XML文件允许标记,但文本   文件没有。

所以,我最好的猜测是,行为上的差异来自于您拥有的Windows 7版本具有与您的vista / XP工作站不同的活动CodePage。

我仍然需要找到如何在系统上获取活动代码页...我最好的猜测是它是在控制面板的区域设置中定义的。但我仍然需要验证这个......

答案 1 :(得分:2)

你遇到了我认为是TWriter.WriteString和TWriter.ReadString方法中的“bug”。 Delphi内部使用这两种方法将TLabel.Caption在设计时从实际的活动对象移动到DFM文件中,然后在运行时返回到活动对象。

如果你查看上述两个例程的代码,你会注意到(我震惊地假设)流入流的实际内容将使用操作系统的默认代码页转换为Unicode!只要开发机器上使用的代码页与测试机器上使用的代码页完全匹配,并且它们可能不匹配,那就很好,花花公子,这很可能是你得到错误的原因。请注意,您为表单上的标题设置的EASTEUROPEAN_CHARSET绝对没有值,因为TWriter.WriteString方法根本不知道它!

我在QC上有关于这个问题的错误报告,它已存在多年......他们可能认为这是“按设计”,但我不认为这是一个非常好的设计。

我重新尝试的解决方案是快速切换到Delphi 2010.我是罗马尼亚的Delphi开发人员,我对这类东西有很多问题,但现在它已经过去了,因为Delphi 2010是UNICODE,因此我不再需要担心代码页转换。

如果您无法切换到Delphi 2010,您可能希望“破解”Classes.pas文件并更改TReader.ReadString例程以始终使用您的代码页进行转换,而不是系统默认值。

答案 2 :(得分:1)

这个问题的答案解决了我的问题:

GetThreadLocale returns different value than GetUserDefaultLCID?

一个解决方案:

我们发现的奇怪的事情是通过控制面板切换到不同的区域设置然后切换回NZ解决了这个问题。我很想知道相同的解决方法是否能解决它只是为了验证我们是否看到了同样的现象。

和第二:

initialization
  SetThreadLocale(LOCALE_USER_DEFAULT);
  GetFormatSettings;

两种解决方案都很有效,应用程序问题也随之消失。

答案 3 :(得分:0)

检查标签的Font.Charset属性。虽然我不知道它是如何被改变的(是否为某些向导预先创建了?) - 它可能与系统有不同的区域设置。