0

I'm new with delphi and I'm trying to figure out how to load specific lines (and not the complete text) from one richtextbox to another one.

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;
LU RD
  • 34,438
  • 5
  • 88
  • 296
user2618164
  • 23
  • 2
  • 5
  • 1
    In order to keep formatting when copying one `TRichEdit` to another, see Zarko Gajic example [`RichEdit Append`](http://delphi.about.com/od/tmemotrichedit/a/richedit-append.htm). – LU RD Feb 20 '14 at 09:35

1 Answers1

3

You do not need a stream to transfer text lines from one TRichEdit to another. Just use the Lines property. Lines is a TStrings type, so use its methods for manipulating the TRichEdit text.

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;

If you want to preserve the RTF formatting, you can use the technique described by Zarko Gajic, Append or Insert RTF from one RichEdit to Another.

Another simple option would be to use the windows clipboard and the 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;

This will also preserve your formatting, copying the selected parts.

If you want to control the selection without user control, use TRichEdit.SelStart to position the caret to the character where the selection starts, and SelLength for the selection length. To position the caret on a specific line, use:

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

If you don't want to use windows clipboard for the copy/paste operation, a stream can be used:

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;
LU RD
  • 34,438
  • 5
  • 88
  • 296
  • 1
    @DavidHeffernan, added a link with a solution for preserving formatting, plus a solution that uses the clipboard to do the same. – LU RD Feb 20 '14 at 14:05
  • +1 but I cannot admire the version that kills the user's clipboard. Very naughty indeed! ;-) – David Heffernan Feb 20 '14 at 14:08
  • @DavidHeffernan, added a pure streaming version. – LU RD Feb 20 '14 at 15:07
  • Nice. But you need `DWORD_PTR` if you want to be 64 bit ready. I'm really picky aren't I?!! ;-) Did you by any chance promulgate the RTF streaming bug from the VCL code? – David Heffernan Feb 20 '14 at 15:08
  • @DavidHeffernan, edited the callback declaration. Still no success with X64 in XE5 :-(. – LU RD Feb 20 '14 at 15:52
  • You mean they've still not fixed the bug in XE5? – David Heffernan Feb 20 '14 at 16:04
  • @DavidHeffernan, I had to add the packed keyword to the TEditStream record declaration to get it working for 64-bit. Should I QC this bug? – LU RD Feb 20 '14 at 22:14
  • Packing seems odd. What does the Windows header file say? – David Heffernan Feb 20 '14 at 22:21
  • @DavidHeffernan, In RichEdit.pas: ` EDITSTREAM = record dwCookie: DWORD_PTR; dwError: Longint; pfnCallback: TEditStreamCallBack; end; TEditStream = EDITSTREAM; `. Compiling with default QWORD alignment. – LU RD Feb 20 '14 at 22:33
  • No, you need to look at the Windows header files. I'd make a C project in VS. Include the relevant header and then use offsetof to query the layout. Or just look for #pragma. Have to go to the true source. – David Heffernan Feb 20 '14 at 22:36
  • @DavidHeffernan, never touched VS. See [`MS EditStream structure`](http://msdn.microsoft.com/en-us/library/windows/desktop/bb787891(v=vs.85).aspx) – LU RD Feb 20 '14 at 22:40
  • Yup. That tells you nothing of the layout. Trust me, this is a field I know well. Only conclusive evidence is to be found in the headers. – David Heffernan Feb 20 '14 at 22:42
  • I bet there's a #pragma(pack, 4) in richedit.h. And if so then it needs to be QC'd. – David Heffernan Feb 20 '14 at 22:45
  • @DavidHeffernan, mea culpa. The RichEdit.pas file specified `{$ALIGN 4}`, so using that it works without packed. – LU RD Feb 20 '14 at 23:18