为什么EM_SETTEXTMODE不起作用?

时间:2014-02-11 19:17:55

标签: delphi winapi windows-messages richedit trichedit

我正在尝试在Delphi 7中的RichEdit控件上使用EM_SETTEXTMODE

只需创建一个新项目,添加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,这意味着文本模式根本没有变化 - 最初是38TM_RICHTEXT or TM_SINGLELEVELUNDO or TM_MULTICODEPAGE),然后是{{ 1}}成功(SETTEXTMODE),但即便如此,它仍然是0

在使用文档建议的38之前,RichEdit的文本已被清除。

我尝试使用EM_SETTEXTMODE设置不同的值,并始终保持EM_SETTEXTMODE

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

我尝试使用RichEdit代替RichEdit1.Perform - 没有区别。

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

知道为什么这不起作用?

1 个答案:

答案 0 :(得分:9)

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

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

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

<强>更新

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

1)在TCustomRichEdit.CreateParams()中,更改

const
  RichEditModuleName = 'RICHED32.DLL';

const
  RichEditModuleName = 'RICHED20.DLL';

CreateSubClass(Params, 'RICHEDIT');

CreateSubClass(Params, 'RICHEDIT20A');

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

if RichEdit.SelStart <> (Selection.cpMax + Length(Str)) then
      raise EOutOfResources.Create(sRichEditInsertError);

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

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;

在Delphi5中这样做,我得到了正确的结果:

Delphi5

要记住的一件事是RichEdit 2.0用CR替换了CRLF对,因此其他问题可能会逐渐增加。如果你在路上遇到问题,请不要开枪......