因此设置如下:
- 制作一个带有TRichEdit控件的新Delphi7应用程序。我们在这里谈论的是非Unicode应用程序
- 在Windows的"区域和语言选项"中安装一种新的输入语言,该语言的编码与非Unicode程序的默认语言的编码不同,例如希腊语
- 在应用程序中添加一个按钮,在其
OnClick
处理程序中添加Button1.Caption := RichEdit1.Text;
,并将其Font.Charset
设置为您刚刚安装的输入语言的字符集(如果我们坚持这个示例,则为GREEK_CHARSET
( -
运行应用程序,切换到新的(希腊语(输入语言,在RichEdit中键入几个字母,然后按下按钮-按钮的标题现在有
????
符号,而不是希腊字符。 -
现在,如果您将非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也无法正常工作(文本再次出现在????
中,而不是正确的字符(,这不仅仅是当您将其分配给String(AnsiString(时。
所以问题来了:
我希望能够正确地将RichEdit的文本转换为字符串(ANSI(,这是基于我选择的字符集,而不是系统的非Unicode程序的默认语言。我该怎么做?我更喜欢一个不涉及第三方组件的解决方案,但当然,如果不可能的话,任何事情都可以。
谢谢!
附言:切换到Delphi 2009或更高版本是不可接受的解决方案。
向底层富编辑窗口发送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;