RichEdit2.0使用单个CR字符作为换行符导致SelStart计算失败(Delphi XE2) [英] RichEdit 2.0's usage of single CR character as linebreak throws off SelStart calculations (Delphi XE2)

查看:0
本文介绍了RichEdit2.0使用单个CR字符作为换行符导致SelStart计算失败(Delphi XE2)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

从Delphi 2006过渡到Delphi XE2时,我们了解到的一件事是,RichEdit2.0将内部CRLF对替换为单个CR字符。这会产生一个不幸的效果,那就是打乱了基于VCL一侧实际文本字符串的所有字符索引计算。

我通过跟踪VCL代码可以看到如下行为:

  1. 发送WM_GETTEXT消息(在TControl.GetTextBuf中完成)将返回包含CRLF对的文本缓冲区。
  2. 发送WM_GETTEXTLENGTH消息(在TControl.GetTextLen中完成)将返回一个值,就像文本仍然包含CRLF个字符一样。
  3. 相反,发送EM_SETSELEX消息(即设置SelStart)会将输入值视为文本仅包含CR个字符。

这会导致应用程序中的各种操作失败(如语法突出显示)。正如您可以看出的那样,在此之前,每一个新行都只有一个字符。

显然,由于这是不一致的行为,我们肯定遗漏了什么或做了什么非常错误的事情。

其他人有从RichEdit1.0到RichEdit2.0控件的转换经验吗?您是如何解决这个问题的?最后,有没有办法强制RichEdit2.0像RichEdit1.0一样使用CRLF对?

推荐答案

我们也遇到了这个问题。

我们做的是"邮件合并"类型的事情,我们的模板带有合并代码,这些代码被解析并替换为来自外部来源的数据。

pos(mystring,RichEdit.Text)与使用RichText.SelStart定位到RichEdit文本的索引不匹配。SelStart中断了我们的合并。

我没有一个好的答案,但我想出了一个解决办法。这有点麻烦(轻描淡写!)但在出现更好的解决方案之前...

解决方法是使用隐藏的TMemo并将RichEdit文本复制到该TMemo,然后将CR/LF对更改为仅CR。然后使用TMemo找到使用pos(字符串,TMemo)的正确位置,并使用该位置获取要在TRichEdit中使用的selstart位置。

这真的很糟糕,但希望这个变通办法能帮助其他与我们处境相同的人,或者激发比我更聪明的人想出更好的解决方案。

我将展示一小段示例代码...

由于我们使用selText替换文本,因此需要同时替换RichEdit控件和TMemo控件中的文本以使这两个控件保持同步。

StartToken和EndToken是合并代码分隔符,是常量。

function TEditForm.ParseTest: boolean;
var TagLength: integer;
var ValueLength: integer;
var ParseStart: integer;
var ParseEnd: integer;
var ParseValue: string;
var Memo: TMemo;
begin
  Result := True;//Default
  Memo := TMemo.Create(nil);
  try
    Memo.Parent := self;
    Memo.Visible := False;
    try
      Memo.Lines.Clear;
      Memo.Lines.AddStrings(RichEditor.Lines);
      Memo.Text := stringreplace(Memo.Text,#13#10,#13,[rfReplaceAll]);//strip CR/LF pairs and replace with CR

      while (Pos(StartToken, Memo.Text) > 0) and (Pos(EndToken, Memo.Text) > 0) do begin
        ParseStart := Pos(StartToken, Memo.SelText);
        ParseEnd := Pos(EndToken, Memo.SelText) + Length(EndToken);
        if ParseStart >= ParseEnd then begin//oops, something's wrong - bail out
          Result := true;
          myEditor.SelStart := 0;
          exit;
        end;
        TagLength := ParseEnd - ParseStart;
        ValueLength := (TagLength - Length(StartToken)) - Length(EndToken);
        ParseValue := Copy(Memo.SelText, (ParseStart + Length(StartToken)), ValueLength);
        Memo.selstart := ParseStart - 1; //since the .text is zero based, but pos is 1 based we subtract 1
        Memo.sellength := TagLength;
        RichEditor.selstart := ParseStart - 1; //since the .text is zero based, but pos is 1 based we subtract 1
        RichEditor.sellength := TagLength;

        TempText := GetValue(ParseValue);
        Memo.SelText := TempText;
        RichEditor.SelText := TempText;
      end;

    except
       on e: exception do
          begin
          MessageDlg(e.message,mtInformation,[mbOK],0);
          result := false;
          end;
       end;//try..except
  finally
    FreeAndNil(Memo);
  end;
end;

这篇关于RichEdit2.0使用单个CR字符作为换行符导致SelStart计算失败(Delphi XE2)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆