【问题标题】:How to copy specific lines from one TRichEdit control to another?如何将特定行从一个 TRichEdit 控件复制到另一个?
【发布时间】:2014-02-20 08:44:13
【问题描述】:

我是 delphi 的新手,我正在尝试弄清楚如何将 特定 行(而不是完整的文本)从一个富文本框加载到另一个富文本框。

procedure TForm1.richedit1change(Sender: TObject);
var
  ms: TMemoryStream;
begin
  ms := TMemoryStream.Create;
  try
    RichEdit1.Lines.SaveToStream(ms);
    ms.Seek(0, soFromBeginning);

    RichEdit2.Lines.LoadFromStream(ms);
  finally
    ms.Free;
  end;
end;

【问题讨论】:

  • 为了在将TRichEdit 复制到另一个时保持格式,请参阅 Zarko Gajic 示例 RichEdit Append

标签: delphi stream trichedit


【解决方案1】:

您不需要流来将文本行从一个TRichEdit 传输到另一个。只需使用 Lines 属性。 LinesTStrings 类型,所以使用它的方法来操作 TRichEdit 文本。

procedure TForm1.richedit1change(Sender: TObject);
var
  i: Integer;
begin
  RichEdit2.Lines.Clear;
  for i := 0 to Pred(RichEdit1.Lines.Count) do
  begin
    if YourSpecificTestFunction(i) then
      RichEdit2.Lines.Add(RichEdit1.Lines[i]);
  end;
end;

如果您想保留 RTF 格式,可以使用 Zarko Gajic Append or Insert RTF from one RichEdit to Another 描述的技术。

另一个简单的选择是使用 windows 剪贴板和 TRichEdit.Selection:

procedure CopyRichEditSelection(Source,Dest: TRichEdit);
begin
  // Copy Source.Selection to Dest via ClipBoard.
  Dest.Clear;
  if (Source.SelLength > 0) then
  begin
    Source.CopyToClipboard;        
    Dest.PasteFromClipboard;
  end;
end;

这也将保留您的格式,复制选定的部分。

如果您想在没有用户控制的情况下控制选择,请使用TRichEdit.SelStart 将插入符号定位到选择开始的字符,并使用SelLength 定位选择长度。要将插入符号定位在特定行上,请使用:

RichEdit1.SelStart := RichEdit1.Perform(EM_LINEINDEX, Line, 0);

如果您不想使用 windows 剪贴板进行复制/粘贴操作,可以使用流:

Uses RichEdit;

function EditStreamOutCallback(dwCookie: DWORD_PTR; pbBuff: PByte; cb: Longint;
  var pcb: LongInt): LongInt; stdcall;
begin
  pcb := cb;
  if cb > 0 then
  begin
    TStream(dwCookie).WriteBuffer(pbBuff^, cb);
    Result := 0;
  end
  else
    Result := 1;
end;

procedure GetRTFSelection(aRichEdit: TRichEdit; intoStream: TStream);
type
  TEditStreamCallBack = function (dwCookie: DWORD_PTR; pbBuff: PByte;
    cb: Longint; var pcb: Longint): Longint; stdcall;

  TEditStream = packed record // <-- Note packed !!
    dwCookie: DWORD_PTR;
    dwError: Longint;
    pfnCallback: TEditStreamCallBack;
  end;

var
  editstream: TEditStream;
begin
  with editstream do
  begin
    dwCookie := DWORD_PTR(intoStream);
    dwError := 0;
    pfnCallback := EditStreamOutCallBack;
  end;
  aRichedit.Perform( EM_STREAMOUT, SF_RTF or SFF_SELECTION, LPARAM(@editstream));
end;

procedure CopyRichEditSelection(Source,Dest: TRichEdit);
var
  aMemStream: TMemoryStream;
begin
  Dest.Clear;
  if (Source.SelLength > 0) then
  begin
    aMemStream := TMemoryStream.Create;
    try
      GetRTFSelection(Source, aMemStream);
      aMemStream.Position := 0;
      Dest.Lines.LoadFromStream(aMemStream);
    finally
      aMemStream.Free;
    end;
  end;
end;

【讨论】:

  • @DavidHeffernan,添加了一个链接,其中包含保留格式的解决方案,以及使用剪贴板执行相同操作的解决方案。
  • +1 但我无法欣赏杀死用户剪贴板的版本。确实很调皮! ;-)
  • @DavidHeffernan,添加了纯流媒体版本。
  • 不错。但是如果你想准备好 64 位,你需要 DWORD_PTR。我真的很挑剔不是吗?!! ;-) 你有没有偶然从 VCL 代码中公布了 RTF 流错误?
  • @DavidHeffernan,编辑了回调声明。 XE5 中的 X64 仍然没有成功 :-(.
猜你喜欢
  • 1970-01-01
  • 2013-08-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-12-30
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多