2006. február 4., szombat

How to feed rich text chunks to a TRichEdit via the clipboard


Problem/Question/Abstract:

It is possible to feed rich text chunks to the control but it is kind of convoluted. There are three options: the clipboard, the rich edits OLE interface, and the EM_STREAMIN message. We concentrate on the clipboard here.

Answer:

The first step is to register a clipboard format for RTF, since this is not a predefined format:

var
  CF_RTF: Word;

CF_RTF := RegisterClipboardFormat('Rich Text Format');

The format name has to appear as typed above, this is the name used by MS Word for Windows and similar MS products.

Note: The Richedit Unit declares a constant CF_RTF, which is not the clipboard format handle but the string you need to pass to RegisterClipboard format! So you can place Richedit into your uses clause and change the line above to

CF_RTF := RegisterClipboardFormat(Richedit.CF_RTF);

The next step is to build a RTF string with the embedded format information. You will get a shock if you inspect the mess of RTF stuff Wordpad (or much worse: Word) will put into the clipboard if you copy just a few characters ), but you can get away with a lot less. The bare minimum would be something like this (inserts a 12 followed by an underlined 44444):

const
  testtext: PChar = '{\rtf1\ansi\pard\plain 12{\ul 44444}}';

The correct balance of opening and closing braces is extremely important, one mismatch and the target app will not be able to interpret the text correctly. If you want to control the font used for the pasted text you need to add a fonttable (the default font is Tms Rmn, not the active font in the target app!). See example testtext2 below. If you want more info, the full RTF specs can be found on www.microsoft.com, a subset is also described in the Windows help compiler docs (hcw.hlp, comes with Delphi).

procedure TForm1.BtnSetRTFClick(Sender: TObject);
const
  testtext: PChar = '{\rtf1\ansi\pard\plain 12{\ul 44444}}';
  testtext2: PChar = '{\rtf1\ansi' +
  '\deff4\deflang1033{\fonttbl{\f4\froman\fcharset0\fprq2 Times New Roman;}}' +
    '\pard\plain 12{\ul 44444}}';
  flap: Boolean = False;
var
  MemHandle: THandle;
  rtfstring: PChar;
begin
  if flap then
    rtfstring := testtext2
  else
    rtfstring := testtext;
  flap := not flap;
  MemHandle := GlobalAlloc(GHND or GMEM_SHARE, StrLen(rtfstring) + 1);
  if MemHandle <> 0 then
  begin
    StrCopy(GlobalLock(MemHandle), rtfstring);
    GlobalUnlock(MemHandle);
    with Clipboard do
    begin
      Open;
      try
        AsText := '1244444';
        SetAsHandle(CF_RTF, MemHandle);
      finally
        Close;
      end;
    end;
  end
  else
    MessageDlg('Global Alloc failed!', mtError, [mbOK], 0);
end;

Once the text is in the clipboard you can call the richedits PasteFromClipboard method to insert it at the caret.

Nincsenek megjegyzések:

Megjegyzés küldése