سؤال

So here's the setup:

  1. Make a new Delphi 7 application with a TRichEdit control on it. We are talking non-Unicode applications here.
  2. Install a new Input language in Windows' Regional and Language Options, that has a different encoding from the encoding of your default Language for non-Unicode programs - for example Greek.
  3. Add a button in the application, and in its 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).
  4. 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.

  5. 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;
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top