为什么EM_SETTEXTMODE不起作用?

jed*_*der 5 delphi winapi richedit windows-messages trichedit

我试图用EM_SETTEXTMODE一个RichEdit在Delphi 7控制.

只需创建一个新项目,添加一个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));
Run Code Online (Sandbox Code Playgroud)

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

根据文档的建议,RichEdit在使用之前清除文本EM_SETTEXTMODE.

我已尝试设置不同的值,EM_SETTEXTMODE它始终保持不变38.

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

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

我在这个问题的各个论坛上找到了几个主题,并且在任何一个论坛中都没有解决.

知道为什么这不起作用?

who*_*ddy 9

较旧的Delphi版本加载位于的RichEdit控件RICHED32.DLL.较新的Delphi版本加载RICHED20.DLL.

RICHED32.DLL暴露了很多问题,比如你的问题.该修复程序正在修改comctrls.pas以便加载它RICHED20.DLL.这很可能是不够的,因为这个DLL和VCL代码可能存在兼容性问题.查找TCustomRichEdit.CreateParams()过程,它包含LoadLibrary调用.

我在Delphi XE中测试了你的代码并且它可以工作,所以你最好的选择是升级到更新的Delphi版本.

UPDATE

我用Delphi 5做了一些测试,似乎足以改变2个功能.将Comctrls.Pas复制到您的项目中并执行以下修改:

1)在TCustomRichEdit.CreateParams(),改变

const
  RichEditModuleName = 'RICHED32.DLL';
Run Code Online (Sandbox Code Playgroud)

const
  RichEditModuleName = 'RICHED20.DLL';
Run Code Online (Sandbox Code Playgroud)

CreateSubClass(Params, 'RICHEDIT');
Run Code Online (Sandbox Code Playgroud)

CreateSubClass(Params, 'RICHEDIT20A');
Run Code Online (Sandbox Code Playgroud)

2)在程序中TRichEditStrings.Insert(),改变

if RichEdit.SelStart <> (Selection.cpMax + Length(Str)) then
      raise EOutOfResources.Create(sRichEditInsertError);
Run Code Online (Sandbox Code Playgroud)

if RichEdit.SelStart <> (Selection.cpMax + Length(Str) - CountLineBreaks(Str)) then
      raise EOutOfResources.Create(sRichEditInsertError);
Run Code Online (Sandbox Code Playgroud)

代码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;
Run Code Online (Sandbox Code Playgroud)

在Delphi5中执行此操作,我得到了正确的结果:

Delphi5

要记住的一件事是RichEdit 2.0用CR取代CRLF对,因此其他问题可能会逐渐增加.如果你遇到问题,不要开枪打我...