【问题标题】:How to detect clipboard text changes?如何检测剪贴板文本更改?
【发布时间】:2020-10-29 06:34:29
【问题描述】:

当剪贴板文本发生变化时,我的应用程序如何接收通知?

例如:

我会启用/禁用粘贴按钮并设置其Hint 属性以显示剪贴板的文本(如'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.

【问题讨论】:

    标签: delphi clipboard delphi-xe7


    【解决方案1】:

    我发现了一个有趣的PDF arcticle,并在文章的“使用剪贴板侦听器 API” 部分相应地编辑了我的示例:

    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.
    

    注意:

    • 它适用于 Windows Vista 及更高版本。

    • 如果您需要支持 Windows XP 和更早版本,则必须使用剪贴板查看器方法(请参阅前面提到的@987654322 的“使用剪贴板查看器链”部分@. 另见SetClipboardViewer()Monitoring Clipboard Contents)

    【讨论】:

    • 表单的Handle 可能会在其生命周期内发生变化,因此最好覆盖表单的虚拟CreateWnd()/DestroyWnd()CreateWindowHandle()/DestroyWindowHandle() 方法来执行 (de )剪贴板监听器的注册。此外,如果您需要支持 XP 及更早版本,请使用 SetClipboardViewer() 而不是 AddClipboardFormatListener()。见Monitoring Clipboard Contents
    • 您的解决方案会对每一个更改做出反应,而不仅仅是文本。无法保证剪贴板内容始终可以转换为文本 - 在您假设内容是文本之前考虑 IsClipboardFormatAvailable() - 您一生中从未复制/粘贴图片或文件吗?
    • @RemyLebeau:感谢您的建议。我已经使用CreateWnd/DestroyWnd 更新了答案,并添加了关于 Windows XP 和早期支持的注释
    • @AmigoJack:如果文本格式不可用,那么Clipboard.AsText 将是一个空字符串并且按钮将被禁用。如果将图片(或任何其他格式)存储到剪贴板中,则收到通知是正确的,因为我可能不得不禁用我的粘贴按钮。我错过了什么吗?
    • 检查格式与剪贴板内容的大小无关——文本也可以轻松填满数百兆字节,而您甚至多次愉快地发出Clipboard.AsText(最重要的是,每次都可能先转换)。根据目标系统性能可能是有限的资源。
    猜你喜欢
    • 2021-06-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-01-11
    • 1970-01-01
    • 2016-04-23
    相关资源
    最近更新 更多