5

我正在尝试在 Delphi 7 中使用控件EM_SETTEXTMODERichEdit

只需创建一个新项目,添加一个TRichEdit控件和一个TButton控件,并将以下代码添加到按钮的单击处理程序中:

  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));

单击按钮后,按钮的标题设置为38 0 38,这意味着文本模式根本没有改变 - 最初是38( TM_RICHTEXT or TM_SINGLELEVELUNDO or TM_MULTICODEPAGE),然后SETTEXTMODE是成功 ( 0),但即使在那之后它仍然是38

按照文档的建议,RichEdit在使用之前清除 's 文本。EM_SETTEXTMODE

我尝试过设置不同的值,EM_SETTEXTMODE它总是保持不变38

我注意到即使控件在调用之前包含文本,它也EM_SETTEXTMODE总是返回(成功)。0RichEdit

我尝试使用RichEdit1.Perform而不是SendMessage- 没有区别。

我在各种论坛上找到了几个关于这个问题的帖子,但没有一个问题得到解决。

知道为什么这不起作用吗?

4

1 回答 1

9

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:

Delphi5

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...

于 2014-02-11T20:34:25.760 回答