How to append formatted text to an existing formatted text in a TRichEdit component (Views: 28)
Problem/Question/Abstract: How to append formatted text to an existing formatted text in a TRichEdit component Answer: Project needs 3 TButtons, 1 TMemo, 1 TRichEdit, 1 TColorDialog, 1 TFontDialog, Uses RichEdit. type TEditStreamCallBack = function(dwCookie: Longint; pbBuff: PByte; cb: Longint; var pcb: Longint): DWORD; stdcall; TEditStream = record dwCookie: Longint; dwError: Longint; pfnCallback: TEditStreamCallBack; end; function EditStreamInCallback(dwCookie: Longint; pbBuff: PByte; cb: Longint; var pcb: Longint): DWORD; stdcall; var theStream: TStream; dataAvail: LongInt; begin theStream := TStream(dwCookie); with theStream do begin dataAvail := Size - Position; Result := 0; {assume everything is ok} if dataAvail <= cb then begin pcb := Read(pbBuff^, dataAvail); if pcb <> dataAvail then {couldn't read req. amount of bytes} result := E_FAIL; end else begin pcb := Read(pbBuff^, cb); if pcb <> cb then result := E_FAIL; end; end; end; function EditStreamOutCallback(dwCookie: Longint; pbBuff: PByte; cb: Longint; var pcb: Longint): DWORD; stdcall; var theStream: TStream; begin theStream := TStream(dwCookie); with theStream do begin if cb > 0 then pcb := Write(pbBuff^, cb); Result := 0; end; end; procedure GetRTFSelection(aRichEdit: TRichEdit; intoStream: TStream); var editstream: TEditStream; begin with editstream do begin dwCookie := Longint(intoStream); dwError := 0; pfnCallback := EditStreamOutCallBack; end; aRichedit.Perform(EM_STREAMOUT, SF_RTF or SFF_SELECTION, longint(@editstream)); end; procedure PutRTFSelection(aRichEdit: TRichEdit; sourceStream: TStream); var editstream: TEditStream; begin with editstream do begin dwCookie := Longint(sourceStream); dwError := 0; pfnCallback := EditStreamInCallBack; end; aRichedit.Perform(EM_STREAMIN, SF_RTF or SFF_SELECTION, longint(@editstream)); end; procedure TForm1.Button2Click(Sender: TObject); var aMemStream: TMemoryStream; begin aMemStream := TMemoryStream.Create; try GetRTFSelection(richedit1, aMemStream); aMemStream.Position := 0; memo1.Lines.LoadFromStream(aMemStream); finally aMemStream.Free; end; end; procedure TForm1.Button3Click(Sender: TObject); var aMemStream: TMemoryStream; begin aMemStream := TMemoryStream.Create; try memo1.Lines.SaveToStream(aMemStream); aMemStream.Position := 0; PutRTFSelection(richedit1, aMemStream); finally aMemStream.Free; end; end; procedure TForm1.RichEdit1KeyDown(Sender: TObject; var Key: Word; Shift: TShiftState); begin if [ssCtrl] = Shift then case Key of Ord('B'): with (Sender as TRichEdit).SelAttributes do if fsBold in Style then Style := Style - [fsBold] else Style := Style + [fsBold]; Ord('U'): with (Sender as TRichEdit).SelAttributes do if fsUnderline in Style then Style := Style - [fsUnderline] else Style := Style + [fsUnderline]; Ord('I'): with (Sender as TRichEdit).SelAttributes do if fsItalic in Style then Style := Style - [fsItalic] else Style := Style + [fsItalic]; Ord('T'): if ColorDialog1.Execute then (Sender as TRichEdit).SelAttributes.Color := ColorDialog1.Color; Ord('F'): if FontDialog1.Execute then (Sender as TRichEdit).SelAttributes.Assign(FontDialog1.Font); end; end; procedure TForm1.RichEdit1KeyPress(Sender: TObject; var Key: Char); begin {Ctrl-I yields a #9 character, a Tab. We have to swallow that.} if (Key = #9) and (GetKeyState(VK_CONTROL) < 0) then Key := #0; end; You now have a simple rich text editor and can type some formatted text into the rich edit. Select some of it and click button2. The selection is fetched and copied as RTF text into the memo. Put the caret somewhere in the rich edit and click button3. The RTF text from the memo is inserted at the selection into the rich edit. To combine several snippets of RTF text into one block one would have to remove the trailing } from block 1, the leading {\rtf1 from block 2 and copy both together into a new block. You can test that with a little cut and paste on the memo before you hit button3. |