【问题标题】:determining the character set to use确定要使用的字符集
【发布时间】:2009-11-13 18:04:45
【问题描述】:

我的 delphi 2009 应用程序有一个使用 GNUGetText 的基本翻译系统。我使用了一些 win API 调用来准备字体。我一直认为它可以正常工作,直到最近来自马耳他的人遇到了我的应用程序在该区域失败的问题。我的应用程序在全球范围内使用。自从 d2009 使用 unicode 以来,其中一些代码可能已经过时了。

为了让我的应用在所有地区都能正常工作,这一切真的有必要吗?

TForm.Font.Charset

据我了解,我必须根据用户的语言环境设置 TForm 实例的 Font.Charset。这是正确的吗?

TranslateCharsetInfo() win API 函数

delphi 2009 的 windows.pas 说:

function TranslateCharsetInfo(var lpSrc: DWORD; var lpCs: TCharsetInfo; 
dwFlags: DWORD): BOOL; 

delphi 5 的 windows.pas 说:

function TranslateCharsetInfo(var lpSrc: DWORD; var lpCs: TCharsetInfo; 
dwFlags: DWORD): BOOL; stdcall;

来自微软的 MSDN:

BOOL TranslateCharsetInfo(
  __inout  DWORD FAR *lpSrc,
  __out    LPCHARSETINFO lpCs,
  __in     DWORD dwFlags
);

回到写这段代码的时候(回到delphi 5天),这个词是函数的inport不正确,正确的方法是:

function TranslateCharsetInfo(lpSrc: Pointer; var lpCs: TCharsetInfo; 
dwFlags: DWORD): BOOL; stdcall; external gdi32;

请注意,d2009 windows.pas 文件副本不是 stdcall。我应该使用哪个 TranslateCharsetInfo 声明?

代码

除此之外,基本上我一直在做以下事情:

var
  Buffer : PChar;
  iSize, iCodePage : integer;
  rCharsetInfo: TCharsetInfo;
begin
  // SysLocale.DefaultLCID = 1802
  iSize := GetLocaleInfo(SysLocale.DefaultLCID, LOCALE_IDefaultAnsiCodePage, 
              nil, 0);
  // size=14
  GetMem(Buffer, iSize);
  try
    if GetLocaleInfo(SysLocale.DefaultLCID, LOCALE_IDefaultAnsiCodePage, Buffer,
      iSize)=0 then
        RaiseLastOSError;

    // Buffer contains 0 so codepage = 0
    iCodePage:=Result := StrToInt(string(Buffer));
  finally
    FreeMem(Buffer);
  end;

  // this function is not called according to MSDN's directions for 
  // TCI_SRCCODEPAGE and the call fails.
  if not TranslateCharsetInfo(Pointer(iCodePage), rCharsetInfo, 
    TCI_SRCCODEPAGE) then
      RaiseLastOSError;

  // acts upon the form
  Font.Charset:= rCharsetInfo.ciCharset;
end;

我只是对此知之甚少...奇怪的是,几年前当我写这篇文章时,我被说服它工作正常。结果...未能检查 API 调用返回码...

难道没有更聪明的方法来做这一切吗? RTL/VCL 不是自动完成大部分/所有这些吗?我的直觉告诉我,我在这方面工作太努力了……

感谢您的帮助!

【问题讨论】:

    标签: delphi localization delphi-2009 translation globalization


    【解决方案1】:

    实际上,我不确定 Delphi 2009,但 MSDN 说:

    请注意,DEFAULT_CHARSET 不是真正的字符集;相反,它是一个类似于 NULL 的常量,表示“以任何可用的字符集显示字符”。

    所以我猜你只需要删除你提到的所有代码,它应该可以工作。

    【讨论】:

    • 感谢您的评论 Lars D!我会请人在这样的语言环境中试用我的应用程序。
    【解决方案2】:

    不是这个问题的真正答案,而是关于在 D2009+ 下使用此代码可能导致内存损坏的“小”注释。函数 GetLocaleInfo “MSDN:返回在区域设置数据缓冲区中检索到的字符数......”而不是 BYTES,因此在 D2009+ 下,您必须为每个字符分配 2 个字节。最好的方法是写:

    GetMem(Buffer, iSize * SizeOf(Char)); //This will be safe for all delphi versions
    

    如果没有这个,您可能会导致无法预测的 AV (D2009+),函数 GetLocaleInfo 可能会覆盖您的内存,因为您分配的缓冲区太小。

    另外,我不明白您为什么要尝试将字符集更改为用户区域设置一,我认为您应该将字符集更改为您的目标翻译(例如,您的程序设置为翻译成俄语,但以英语运行操作系统,那么您需要将字符集更改为 RUSSIAN_CHARSET,而不是 ANSI_CHARSET)。在 D2009+ 下我不确定是否需要这样做,但我可能错了。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-02-22
      • 2011-11-11
      • 2011-06-27
      相关资源
      最近更新 更多