4

所以这里是设置:

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

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

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

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

此外,将.Text值分配给 WideString 或 UnicodeString 也无法正常工作(文本再次出现????而不是正确的字符),不仅是在将其分配给字符串 (AnsiString) 时。

那么问题来了:

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

谢谢!

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

4

1 回答 1

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;
于 2013-04-01T10:41:57.323 回答