So here's the setup:
OnClick
handler add Button1.Caption := RichEdit1.Text;
, and set its Font.Charset
to the charset of the input language you just installed (GREEK_CHARSET
if we stick to this example).Run the application, switch to your new (Greek) input language, type a few letters in the RichEdit and press the button - the button's caption now has ????
symbols instead of Greek characters.
Now, if you set your default Language for non-Unicode programs to Greek (Windows restart required), this problem would disappear - greek characters would appear properly. Set your default Language for non-Unicode programs back to what it was before and the problem is there again.
So I would guess that TRichEdit works with Unicode internally, as changing its Font.Charset value never changes anything - the RichEdit accepts any installed Input language properly, and if you have installed two different non-latin languages which use different character sets (Greek /GREEK_CHARSET
/ and Russian /RUSSIAN_CHARSET
/ for example) it would accept them both without changing its Font.Charset.
I would also guess that when you get the .Text
(or .Lines[i]
) value of the TRichEdit, it converts its internal Unicode text to ANSI, based on the Windws' default Language for non-Unicode programs.
Further more, assigning the .Text
value to a WideString or a UnicodeString also doesn't work properly (the text is once again in ????
instead of the proper characters), it's not only when you assign it to a String (AnsiString).
So here's the question:
I want to be able to convert the text of a RichEdit to a String (ANSI) properly, based on a character set of my choosing instead of the system's default Language for non-Unicode programs. How can I do that? I would prefer a solution that doesn't involve third party components, but, of course, if not possible - anything would do.
Thanks!
P.S.: Switching to Delphi 2009 or later is not an acceptable solution.
Send the underlying rich edit window the EM_GETTEXTEX
message. You pass a GETTEXTEX
struct which specifies the code page.
So, something like this would pull the text out into a UTF-16 encoded 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;
You can then convert that UTF-16 string to whatever code page you like. If you'd rather pull it out in a specific code page directly, then do it like this:
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;