2010. szeptember 4., szombat

How to append formatted text to an existing formatted text in a TRichEdit component


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.

Nincsenek megjegyzések:

Megjegyzés küldése