Fabrizio
Fabrizio

Reputation: 8043

How to detect clipboard text changes?

How can my application receive a notification when the clipboard text changes?

For example:

I would to enable/disable a paste button and setting its Hint property in order to display the clipboard's text (like 'Paste "%s"')

unit Unit1;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls;

type
  TMyPasteForm = class(TForm)
    MyPasteButton: TButton;
    MyEdit: TEdit;
    procedure MyPasteButtonClick(Sender: TObject);
    procedure FormCreate(Sender: TObject);
  private
    procedure SyncMyPasteButton();
    { Private declarations }
  public
    { Public declarations }
  end;

var
  MyPasteForm: TMyPasteForm;

implementation

{$R *.dfm}

uses
  Clipbrd;

procedure TMyPasteForm.FormCreate(Sender: TObject);
begin
  MyPasteButton.ShowHint := True;
end;

procedure TMyPasteForm.MyPasteButtonClick(Sender: TObject);
begin
  MyEdit.Text := Clipboard.AsText;
end;

procedure TMyPasteForm.SyncMyPasteButton();
begin
  MyPasteButton.Enabled := Length(Clipboard.AsText) > 0;
  MyPasteButton.Hint := Format('Paste "%s"', [Clipboard.AsText]);
end;

end.

Upvotes: 3

Views: 1668

Answers (1)

Fabrizio
Fabrizio

Reputation: 8043

I've found an interesting PDF arcticle and edited my example accordingly with the "Using the clipboard listener API" section of the article:

unit Unit1;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls;

type
  TMyPasteForm = class(TForm)
    MyPasteButton: TButton;
    MyEdit: TEdit;
    procedure MyPasteButtonClick(Sender: TObject);
    procedure FormCreate(Sender: TObject);
  private
    procedure SyncMyPasteButton();
    procedure WMClipboardUpdate(var Msg : TMessage); message WM_CLIPBOARDUPDATE;
  protected
    procedure CreateWnd(); override;
    procedure DestroyWnd(); override;
  public
    { Public declarations }
  end;

var
  MyPasteForm: TMyPasteForm;

implementation

{$R *.dfm}

uses
  Clipbrd;

procedure TMyPasteForm.FormCreate(Sender: TObject);
begin
  MyPasteButton.ShowHint := True;

  SyncMyPasteButton();
end;

procedure TMyPasteForm.CreateWnd();
begin
  inherited;
  //making sure OS notify this window when clipboard content changes
  AddClipboardFormatListener(Handle);
end;

procedure TMyPasteForm.DestroyWnd();
begin
  //remove the clipboard listener
  RemoveClipboardFormatListener(Handle);
  inherited;
end;

procedure TMyPasteForm.MyPasteButtonClick(Sender: TObject);
begin
  MyEdit.Text := Clipboard.AsText;
end;

procedure TMyPasteForm.SyncMyPasteButton();
begin
  MyPasteButton.Enabled := IsClipboardFormatAvailable(CF_TEXT);

  if(MyPasteButton.Enabled) then
    MyPasteButton.Hint := Format('Paste "%s"', [Clipboard.AsText])
  else
    MyPasteButton.Hint := '';
end;

procedure TMyPasteForm.WMClipboardUpdate(var Msg : TMessage);
begin
  //the clipboard content is changed!
  SyncMyPasteButton();
end;

end.

Note:

  • It works for Windows Vista and later.

  • If you need to support Windows XP and earlier you must use a clipboard viewer approach (See the "Using the clipboard viewer chain" section of the previously mentioned article. See also SetClipboardViewer() and Monitoring Clipboard Contents)

Upvotes: 4

Related Questions