I'm trying to use EM_SETTEXTMODE
on a RichEdit
control in Delphi 7.
Just create a new project, add a TRichEdit
control and a TButton
control and add the following code to the button's click handler:
SendMessage(RichEdit1.Handle, WM_SETTEXT, 0, LPARAM(PChar('')));
Button1.Caption := IntToStr(SendMessage(RichEdit1.Handle, EM_GETTEXTMODE, 0, 0));
Button1.Caption := Button1.Caption + ' ' + IntToStr(SendMessage(RichEdit1.Handle, EM_SETTEXTMODE, TM_PLAINTEXT, 0));
Button1.Caption := Button1.Caption + ' ' + IntToStr(SendMessage(RichEdit1.Handle, EM_GETTEXTMODE, 0, 0));
The button's caption is set to 38 0 38
after clicking on the button, meaning the text mode didn't change at all - initially it was 38
(TM_RICHTEXT or TM_SINGLELEVELUNDO or TM_MULTICODEPAGE
), then SETTEXTMODE
was successful (0
) but even after that it is still 38
.
The RichEdit
's text is cleared before using EM_SETTEXTMODE
as suggested by the documentation.
I've tried setting different values with EM_SETTEXTMODE
and it always stays 38
.
I noticed that EM_SETTEXTMODE
always returns 0
(success) even if the RichEdit
control contains text before calling it.
I tried using RichEdit1.Perform
instead of SendMessage
- no difference.
I've found several threads in various forums on this issue, and it wasn't resolved in any of them.
Any idea why isn't this working?
Older Delphi versions load the RichEdit control which is located in RICHED32.DLL
.
Newer Delphi versions load RICHED20.DLL
.
RICHED32.DLL
exposes many problems, like yours.
The fix is modifying comctrls.pas so that it loads RICHED20.DLL
. That will most likely not be enough as there may be compatibility issues with this DLL and the VCL code.
Look for the TCustomRichEdit.CreateParams()
procedure, it contains the LoadLibrary call.
I tested your code in Delphi XE and there it works, so your best option is to upgrade to a more recent Delphi version.
UPDATE
I did some tests with Delphi 5 and it seems to be enough to change 2 functions. Copy Comctrls.Pas into your project and execute these modifications:
1) in TCustomRichEdit.CreateParams()
, change
const
RichEditModuleName = 'RICHED32.DLL';
into
const
RichEditModuleName = 'RICHED20.DLL';
and
CreateSubClass(Params, 'RICHEDIT');
into
CreateSubClass(Params, 'RICHEDIT20A');
2) in the procedure TRichEditStrings.Insert()
, change
if RichEdit.SelStart <> (Selection.cpMax + Length(Str)) then
raise EOutOfResources.Create(sRichEditInsertError);
into
if RichEdit.SelStart <> (Selection.cpMax + Length(Str) - CountLineBreaks(Str)) then
raise EOutOfResources.Create(sRichEditInsertError);
code for CountLineBreaks/PosEx
:
function PosEx(const SubStr, S: string; Offset: Cardinal = 1): Integer;
var
Tmp: PChar;
begin
Result := 0;
if (Offset > Cardinal(Length(S))) then exit;
if Offset = 1 then
Result := Pos(SubStr, S)
else
begin
Tmp := StrPos(PChar(@S[Offset]), PChar(SubStr));
if Tmp = nil then exit;
Result := Cardinal(Tmp - PChar(@S[Offset])) + Offset;
end;
end;
function CountLineBreaks(const S: string): Integer;
const
LB = #13#10;
var
P: Integer;
begin
Result := 0;
P := Pos(LB, S);
while P <> 0 do
begin
Inc(Result);
P := PosEx(LB, S, P + 2);
end;
end;
Doing this in Delphi5, I get the correct result:
One thing to keep in mind is that RichEdit 2.0 replaces CRLF pairs with CR, so other issues may creep up. Don't shoot me if you run into problems down the road...