delphi - RichEdit 2.0 使用单个 CR 字符作为换行符会导致 SelStart 计算失败 (Delphi XE2)

标签 delphi newline delphi-xe2 richedit

从 Delphi 2006 过渡到 Delphi XE2 时,我们了解到的一件事是 RichEdit 2.0 将内部 CRLF 对替换为单个 CR 字符。这会带来不幸的结果,即放弃基于 VCL 端实际文本字符串的所有字符索引计算。

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

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

这会导致我们的应用程序中出现各种失败(例如语法突出显示)。正如您所见,到那时为止,每一行新行的所有内容都精确地偏离了一个字符。

显然,由于这是不一致的行为,我们一定是遗漏了某些东西或者做了一些非常错误的事情。

还有其他人有从 RichEdit 1.0 过渡到 RichEdit 2.0 控件的经验吗?您是如何解决这个问题的?最后,有没有办法强制RichEdit 2.0像RichEdit 1.0一样使用CRLF对?

最佳答案

我们也遇到了这个问题。

我们做了“邮件合并”类型的事情,其中​​我们有带有合并代码的模板,这些代码被来自外部源的数据解析和替换。

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

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

解决方法是使用隐藏的 TMemo 并将 RichEdit 文本复制到其中,并将 CR/LF 对更改为仅 CR。然后使用 TMemo 使用 pos(string, 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;

关于delphi - RichEdit 2.0 使用单个 CR 字符作为换行符会导致 SelStart 计算失败 (Delphi XE2),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8725457/

相关文章:

perl - IO::Socket:SSL 在套接字上打印时有时会添加换行符

java - JTextArea 行到 ArrayList<String>

delphi - 列出实现接口(interface)的类的所有属性

delphi - FireMonkey 应用程序中的 TFileOpenDialog

delphi - 当所有者是 MDI Child 时,如何定位 TForm poOwnerFormCenter?

delphi - 为什么包含过程时 Delphi 记录的大小没有增加?

delphi - TDataSet.Insert 和 TDataSet.Append 有什么区别?

arrays - 如何在 Swift 中用新行拆分字符串

ios - Delphi XE2 应用程序在 IPAD 上没有响应

delphi - 如何获取加密数据的大小?