Difference between revisions of "Clipboard"

From Free Pascal wiki
Jump to navigationJump to search
Line 112: Line 112:
  
 
==Custom format==
 
==Custom format==
 +
 +
==Multiple objects==
 +
 +
==Getting notified of changes==
 +
 +
The LCL does not pass on windows messages. It only passes on messages > WM_USER. This means you have to write your own message handler. [http://wiki.lazarus.freepascal.org/Win32/64_Interface#Processing_non-user_messages_in_your_window Processing non - user messages in your window]
 +
 +
Sample code to implement message handler:
 +
 +
<delphi>unit Unit1;
 +
 +
{$mode delphi}{$H+}
 +
 +
interface
 +
 +
uses
 +
  Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs,
 +
  Clipbrd, StdCtrls, Windows, Messages;
 +
 +
type
 +
  TForm1 = class(TForm)
 +
    Button1: TButton;
 +
    procedure FormCreate(Sender: TObject);
 +
    procedure FormDestroy(Sender: TObject);
 +
  private
 +
    FNextClipboardOwner: HWnd;  // handle to the next viewer
 +
    // Here are the clipboard event handlers
 +
    function WMChangeCBChain(wParam: WParam; lParam: LParam):LRESULT;
 +
    function WMDrawClipboard(wParam: WParam; lParam: LParam):LRESULT;
 +
  public
 +
  end;
 +
 +
var
 +
  Form1: TForm1;
 +
 +
implementation
 +
 +
{$R *.lfm}
 +
var
 +
  PrevWndProc:windows.WNDPROC;
 +
 +
function WndCallback(Ahwnd: HWND; uMsg: UINT; wParam: WParam;
 +
  lParam: LParam): LRESULT; stdcall;
 +
begin
 +
  if uMsg = WM_CHANGECBCHAIN then begin
 +
    Result := Form1.WMChangeCBChain(wParam, lParam);
 +
    Exit;
 +
  end
 +
  else if uMsg=WM_DRAWCLIPBOARD then begin
 +
    Result := Form1.WMDrawClipboard(wParam, lParam);
 +
    Exit;
 +
  end;
 +
  Result := CallWindowProc(PrevWndProc, Ahwnd, uMsg, WParam, LParam);
 +
end;
 +
 +
{ TForm1 }
 +
 +
procedure TForm1.FormCreate(Sender: TObject);
 +
begin
 +
  PrevWndProc := Windows.WNDPROC(SetWindowLong(Self.Handle, GWL_WNDPROC, PtrInt(@WndCallback)));
 +
  FNextClipboardOwner := SetClipboardViewer(Self.Handle);
 +
end;
 +
 +
procedure TForm1.FormDestroy(Sender: TObject);
 +
begin
 +
  ChangeClipboardChain(Handle, FNextClipboardOwner);
 +
end;
 +
 +
function TForm1.WMChangeCBChain(wParam: WParam; lParam: LParam): LRESULT;
 +
var
 +
  Remove, Next: THandle;
 +
begin
 +
  Remove := WParam;
 +
  Next := LParam;
 +
  if FNextClipboardOwner = Remove then FNextClipboardOwner := Next
 +
    else if FNextClipboardOwner <> 0 then
 +
      SendMessage(FNextClipboardOwner, WM_ChangeCBChain, Remove, Next)
 +
end;
 +
 +
function TForm1.WMDrawClipboard(wParam: WParam; lParam: LParam): LRESULT;
 +
begin
 +
  if Clipboard.HasFormat(CF_TEXT) Then Begin
 +
    ShowMessage(Clipboard.AsText);
 +
  end;
 +
  SendMessage(FNextClipboardOwner, WM_DRAWCLIPBOARD, 0, 0);  // VERY IMPORTANT
 +
  Result := 0;
 +
end;
 +
 +
end.</delphi>
  
 
==External links==
 
==External links==
  
 
* [http://delphi.about.com/od/vclusing/a/tclipboard.htm Basic Clipboard Operations (Cut/Copy/Paste) using the TClipboard object]
 
* [http://delphi.about.com/od/vclusing/a/tclipboard.htm Basic Clipboard Operations (Cut/Copy/Paste) using the TClipboard object]

Revision as of 13:10, 27 January 2012

Predefined types

TPredefinedClipboardFormat MIME type
pcfText text/plain
pcfBitmap image/bmp
pcfPixmap image/xpm
pcfIcon image/lcl.icon
pcfPicture image/lcl.picture
pcfObject application/lcl.object
pcfComponent application/lcl.component
pcfCustomData application/lcl.customdata
pcfDelphiText text/plain
pcfDelphiBitmap text/delphi.bitmap
pcfDelphiPicture Delphi picture
pcfDelphiMetaFilePict image/delphimetafilepict
pcfDelphiObject application/delphi.object
pcfDelphiComponent Delphi component
pcfKylixPicture image/delphi.picture
pcfKylixBitmap image/delphi.bitmap
pcfKylixDrawing image/delphi.drawing
pcfKylixComponent application/delphi.component

Text

For use of simple text Clipboard offer property AsText which can be used for reading an writing plain text.

Writing text: <delphi>Clipboard.AsText := 'Hello clipboard!';</delphi>

Reading text: <delphi>ShowMessage('Clipboard content: ' + Clipboard.AsText);</delphi>

Text oriented components

Some visual components like TEdit, TMemo, TStringGrid, TLabeledEdit, TMaskEdit, TSpinEdit and TFloatSpinEdit have ability to select a part of contained text and offer additional functionality for handling clipboard operations on selected text.

<delphi> procedure CopyToClipboard;

 procedure CutToClipboard; 
 procedure PasteFromClipboard;</delpi>

HTML source

<delphi>uses

 Clipbrd, ...;

procedure InsertHTMLSourceFromClipboard(Strings: TString); var

 Fid: TClipboardFormat
 Str: WideString;
 Stream: TMemoryStream;

begin

 Fid := Clipboard.FindFormatID('text/html');
 if Fid <> 0 then 
 try
   Stream := TMemoryStream.Create;
   if Clipboard.GetFormat(Fid, Stream) then 
   begin
     Stream.Position := 0;
     Str := PWideChar(Stream.Memory);
     Str[(Stream.Size div 2) + 1] := #0;
     Strings.Text := UTF8Encode(Str);
   end;
 finally
   Stream.Free;
 end;

end;</delphi>

Image

Load from clipboard

<delphi>uses

 Clipbrd, LCLIntf, LCLType, ...;

procedure LoadBitmapFromClipboard(Bitmap: TBitmap); begin

 if Clipboard.HasFormat(PredefinedClipboardFormat(pcfDelphiBitmap)) then
   Bitmap.LoadFromClipboardFormat(PredefinedClipboardFormat(pcfDelphiBitmap));
 if Clipboard.HasFormat(PredefinedClipboardFormat(pcfBitmap)) then
   Bitmap.LoadFromClipboardFormat(PredefinedClipboardFormat(pcfBitmap));

end;</delphi>

Save to clipboard

<delphi>uses

 Clipbrd, ...;

procedure SaveBitmapToClipboard(Bitmap: TBitmap); begin

 Clipboard.Assign(Bitmap);

end;</delphi>

Custom format

Multiple objects

Getting notified of changes

The LCL does not pass on windows messages. It only passes on messages > WM_USER. This means you have to write your own message handler. Processing non - user messages in your window

Sample code to implement message handler:

<delphi>unit Unit1;

{$mode delphi}{$H+}

interface

uses

 Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs,
 Clipbrd, StdCtrls, Windows, Messages;

type

 TForm1 = class(TForm)
   Button1: TButton;
   procedure FormCreate(Sender: TObject);
   procedure FormDestroy(Sender: TObject);
 private
   FNextClipboardOwner: HWnd;   // handle to the next viewer
   // Here are the clipboard event handlers
   function WMChangeCBChain(wParam: WParam; lParam: LParam):LRESULT;
   function WMDrawClipboard(wParam: WParam; lParam: LParam):LRESULT;
 public
 end;

var

 Form1: TForm1;

implementation

{$R *.lfm} var

 PrevWndProc:windows.WNDPROC;

function WndCallback(Ahwnd: HWND; uMsg: UINT; wParam: WParam;

 lParam: LParam): LRESULT; stdcall;

begin

 if uMsg = WM_CHANGECBCHAIN then begin
   Result := Form1.WMChangeCBChain(wParam, lParam);
   Exit;
 end 
 else if uMsg=WM_DRAWCLIPBOARD then begin
   Result := Form1.WMDrawClipboard(wParam, lParam);
   Exit;
 end;
 Result := CallWindowProc(PrevWndProc, Ahwnd, uMsg, WParam, LParam);

end;

{ TForm1 }

procedure TForm1.FormCreate(Sender: TObject); begin

 PrevWndProc := Windows.WNDPROC(SetWindowLong(Self.Handle, GWL_WNDPROC, PtrInt(@WndCallback)));
 FNextClipboardOwner := SetClipboardViewer(Self.Handle);

end;

procedure TForm1.FormDestroy(Sender: TObject); begin

 ChangeClipboardChain(Handle, FNextClipboardOwner);

end;

function TForm1.WMChangeCBChain(wParam: WParam; lParam: LParam): LRESULT; var

 Remove, Next: THandle;

begin

 Remove := WParam;
 Next := LParam;
 if FNextClipboardOwner = Remove then FNextClipboardOwner := Next
   else if FNextClipboardOwner <> 0 then
     SendMessage(FNextClipboardOwner, WM_ChangeCBChain, Remove, Next)

end;

function TForm1.WMDrawClipboard(wParam: WParam; lParam: LParam): LRESULT; begin

 if Clipboard.HasFormat(CF_TEXT) Then Begin
   ShowMessage(Clipboard.AsText);
 end;
 SendMessage(FNextClipboardOwner, WM_DRAWCLIPBOARD, 0, 0);   // VERY IMPORTANT
 Result := 0;

end;

end.</delphi>

External links