2007. február 8., csütörtök

How to copy rich text from a TRichEdit to the clipboard


Problem/Question/Abstract:

I have used the TRichEdit component to generate some rich text which I am now holding in a byte array. How can I paste it to the clipboard so that it can be copied into MS Word?

Answer:

You have to copy it to the clipboard with a specific format. The richedit unit defines a string constant CF_RTF (very unfortunate name!). You feed that to RegisterClipboardFormat to obtain a format identifier which you can then use with Clipboard.SetAshandle.

If you write the data to a memorystream you can use the following procedure to copy the streams content to the clipboard. Use the format identifier you obtained from CF_RTF as first parameter.

procedure CopyStreamToClipboard(fmt: Cardinal; S: TStream);
var
  hMem: THandle;
  pMem: Pointer;
begin
  {Rewind stream position to start}
  S.Position := 0;
  {Allocate a global memory block the size of the stream data}
  hMem := GlobalAlloc(GHND or GMEM_DDESHARE, S.Size);
  if hMem <> 0 then
  begin
    {Succeeded, lock the memory handle to get a pointer to the memory}
    pMem := GlobalLock(hMem);
    if pMem <> nil then
    begin
      {Succeeded, now read the stream contents into the memory the pointer points at}
      try
        S.Read(pMem^, S.Size);
        {Rewind stream again, caller may be confused if the stream position is
                                left at the end}
        S.Position := 0;
      finally
        {Unlock the memory block}
        GlobalUnlock(hMem);
      end;
      {Open clipboard and put the block into it. The way the Delphi clipboard
                        object is written this will clear the clipboard first. Make sure the
                        clipboard is closed even in case of an exception. If left open it would
                        become unusable for other apps.}
      Clipboard.Open;
      try
        Clipboard.SetAsHandle(fmt, hMem);
      finally
        Clipboard.Close;
      end;
    end
    else
    begin
      {Could not lock the memory block, so free it again and raise an out of
                        memory exception}
      GlobalFree(hMem);
      OutOfMemoryError;
    end;
  end
  else
    {Failed to allocate the memory block, raise exception}
    OutOfMemoryError;
end;

Nincsenek megjegyzések:

Megjegyzés küldése