确定要使用的字符集

时间:2009-11-13 18:04:46

标签: delphi localization delphi-2009 translation globalization

我的delphi 2009应用程序有一个使用GNUGetText的基本翻译系统。我使用了一些win API调用来准备字体。直到最近,当马耳他的某个人的应用程序出现问题时,我认为它才能正常工作。我的应用程序全局使用。由于d2009使用unicode,因此部分代码可能已经过时。

是否真的有必要让我的应用在所有区域设置中运行?

TForm.Font.Charset

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

TranslateCharsetInfo()获取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;

来自microsoft的MSDN:

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

当这段代码被写回来时(回到delphi 5天),这个单词是函数的输入不正确而且正确的方法是:

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不能自动完成大部分/全部操作吗?我的直觉告诉我,我正在努力工作......

谢谢你的帮助!

2 个答案:

答案 0 :(得分:1)

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

  

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

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

答案 1 :(得分:0)

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

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

如果没有这个你可以导致不可预知的AV(D2009 +),函数GetLocaleInfo可以覆盖你的内存,因为你已经分配了太小的缓冲区。

另外我不明白你为什么要尝试将变更字符集改为用户区域设置,我认为你应该将charset更改为你的目标翻译(比如,你的程序设置为翻译成俄语,但是用英语运行) OS,那么你需要将charset更改为RUSSIAN_CHARSET,而不是ANSI_CHARSET)。在D2009 +我不确定是否需要这个,但我可能错了。