Delphi:TRichEdit非默认非Unicode系统语言中的文本字符串(ANSI)

时间:2013-04-01 10:31:58

标签: delphi delphi-7 richedit input-language

所以这是设置:

  1. 使用TRichEdit控件创建一个新的Delphi 7应用程序。我们在这里谈论非Unicode应用程序。
  2. 在Windows的区域和语言选项中安装新的输入语言,其编码与default Language for non-Unicode programs 的编码不同 - 例如希腊语。
  3. 在应用程序中添加一个按钮,并在其OnClick处理程序中添加Button1.Caption := RichEdit1.Text;,并将其Font.Charset设置为您刚安装的输入语言的字符集(GREEK_CHARSET如果我们坚持这个例子)。
  4. 运行应用程序,切换到新的(希腊语)输入语言,在RichEdit中输入几个字母并按下按钮 - 按钮的标题现在有????符号而不是希腊字符。

  5. 现在,如果您将非Unicode程序的默认语言设置为希腊语(需要重新启动Windows),则此问题将消失 - 希腊字符将正确显示。将非Unicode程序的默认语言设置回原来的状态,然后又出现问题。

  6. 所以我猜测TRichEdit在内部使用Unicode,因为更改其Font.Charset值永远不会改变任何东西 - RichEdit正确接受任何已安装的输入语言,并且如果您安装了两种使用不同字符集的不同非拉丁语言(希腊语/ GREEK_CHARSET /和俄语/ RUSSIAN_CHARSET /例如)它会接受它们而不更改其Font.Charset。

    我还猜测当你获得TRichEdit的.Text(或.Lines[i])值时,它会根据Windws的默认语言将其内部Unicode文本转换为ANSI。非Unicode程序

    此外,将.Text值分配给WideString或UnicodeString也无法正常工作(文本再次位于????而不是正确的字符中),不仅仅是当你将它分配给一个字符串(AnsiString)。

    所以这就是问题:

    我希望能够根据我选择的字符集正确地将RichEdit的文本转换为字符串(ANSI),而不是系统的非Unicode程序的默认语言。我怎样才能做到这一点?我更喜欢不涉及第三方组件的解决方案,当然,如果不可能的话 - 任何事情都可以。

    谢谢!

    P.S。:切换到Delphi 2009或更高版本是不可接受的解决方案。

1 个答案:

答案 0 :(得分:5)

向基础富编辑窗口发送EM_GETTEXTEX消息。您传递了一个指定代码页的GETTEXTEX结构。

所以,像这样的东西会将文本拉成UTF-16编码WideString

function GetRichEditText(RichEdit: TRichEdit): WideString;
var
  GetTextLengthEx: TGetTextLengthEx;
  GetTextEx: TGetTextEx;
  Len: Integer;
begin
  GetTextLengthEx.flags := GTL_DEFAULT;
  GetTextLengthEx.codepage := 1200;
  Len := SendMessage(RichEdit.Handle, EM_GETTEXTLENGTHEX, 
    WPARAM(@GetTextLengthEx), 0);
  if Len=E_INVALIDARG then
    raise Exception.Create('EM_GETTEXTLENGTHEX failed');
  SetLength(Result, Len);
  if Len=0 then
    exit;
  GetTextEx.cb := (Length(Result)+1)*SizeOf(WideChar);
  GetTextEx.flags := GTL_DEFAULT;
  GetTextEx.codepage := 1200;
  GetTextEx.lpDefaultChar := nil;
  GetTextEx.lpUsedDefChar := nil;
  SendMessage(RichEdit.Handle, EM_GETTEXTEX, WPARAM(@GetTextEx), 
    LPARAM(PWideChar(Result)));
end;

然后,您可以将该UTF-16字符串转换为您喜欢的任何代码页。如果您想直接在特定的代码页中将其拉出来,那就这样做:

function GetRichEditText(RichEdit: TRichEdit; AnsiCodePage: UINT): AnsiString;
var
  GetTextLengthEx: TGetTextLengthEx;
  GetTextEx: TGetTextEx;
  Len: Integer;
begin
  GetTextLengthEx.flags := GTL_DEFAULT;
  GetTextLengthEx.codepage := AnsiCodePage;
  Len := SendMessage(RichEdit.Handle, EM_GETTEXTLENGTHEX, 
    WPARAM(@GetTextLengthEx), 0);
  if Len=E_INVALIDARG then
    raise Exception.Create('EM_GETTEXTLENGTHEX failed');
  SetLength(Result, Len);
  if Len=0 then
    exit;
  GetTextEx.cb := (Length(Result)+1)*SizeOf(AnsiChar);
  GetTextEx.flags := GTL_DEFAULT;
  GetTextEx.codepage := AnsiCodePage;
  GetTextEx.lpDefaultChar := nil;
  GetTextEx.lpUsedDefChar := nil;
  SendMessage(RichEdit.Handle, EM_GETTEXTEX, WPARAM(@GetTextEx), 
    LPARAM(PWideChar(Result)));
end;