You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何通过Delphi FireMonkey剪贴板服务检测剪贴板内容变化?

Delphi FireMonkey跨平台剪贴板实时更新方案

一、原生平台监听(推荐方案)

FMX的ClipboardServices确实未内置剪贴板变化监听机制,因此需要针对Windows和macOS分别编写原生平台代码实现实时监听:

Windows平台

利用Win32 API的剪贴板查看器机制,系统会在剪贴板内容变化时主动发送消息通知:

  1. 通过窗口Handle注册剪贴板查看器;
  2. 重写窗口消息处理逻辑,捕获WM_DRAWCLIPBOARD(剪贴板内容变化)和WM_CHANGECBCHAIN(查看器链变更)消息;
  3. 收到消息后调用FMX剪贴板API判断是否有文本,有则更新Memo。

代码片段示例:

private
  NextClipboardViewer: HWND;
procedure WndProc(var Message: TMessage); override;

procedure TForm1.FormCreate(Sender: TObject);
begin
  NextClipboardViewer := SetClipboardViewer(Handle);
end;

procedure TForm1.WndProc(var Message: TMessage);
begin
  inherited;
  case Message.Msg of
    WM_DRAWCLIPBOARD:
    begin
      if TClipboard.Current.HasText then
        Memo1.Text := TClipboard.Current.GetText;
      // 传递消息给下一个查看器
      if NextClipboardViewer <> 0 then
        SendMessage(NextClipboardViewer, Message.Msg, Message.WParam, Message.LParam);
    end;
    WM_CHANGECBCHAIN:
    begin
      if Message.WParam = NextClipboardViewer then
        NextClipboardViewer := Message.LParam
      else if NextClipboardViewer <> 0 then
        SendMessage(NextClipboardViewer, Message.Msg, Message.WParam, Message.LParam);
    end;
  end;
end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
  ChangeClipboardChain(Handle, NextClipboardViewer);
end;

macOS平台

基于Cocoa框架的NSPasteboard通知机制监听剪贴板变化:

  1. 获取系统通用剪贴板实例;
  2. 添加观察者监听NSPasteboardChangedNotification通知;
  3. 收到通知后切换到UI线程更新Memo(避免跨线程操作FMX控件)。

代码片段示例:

uses
  Macapi.AppKit, Macapi.Foundation, Macapi.ObjectiveC, System.Classes;

private
  FPasteboardObserver: NSObject;
procedure OnPasteboardChanged(Notification: NSNotification);

procedure TForm1.FormCreate(Sender: TObject);
var
  Block: TNotifyNSNotification;
begin
  Block := procedure(Notification: NSNotification)
    begin
      OnPasteboardChanged(Notification);
    end;
  FPasteboardObserver := TNSBlockObserver.Create(Block);
  NSPasteboard.generalPasteboard.addObserverForNameObjectQueueUsingBlock(
    NSPasteboardChangedNotification, nil, nil, FPasteboardObserver.Block
  );
end;

procedure TForm1.OnPasteboardChanged(Notification: NSNotification);
begin
  if TClipboard.Current.HasText then
  begin
    TThread.Synchronize(nil, procedure
      begin
        Memo1.Text := TClipboard.Current.GetText;
      end);
  end;
end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
  NSPasteboard.generalPasteboard.removeObserverNameObject(
    FPasteboardObserver, NSPasteboardChangedNotification, nil
  );
end;

二、TTimer轮询方案(快速实现方案)

用TTimer定期检测剪贴板是可行的,需注意以下细节:

  • 轮询间隔:1秒间隔在多数场景下足够,若需更实时可缩短至500ms,系统开销可忽略;
  • 避免重复更新:记录上一次剪贴板文本,仅当内容变化时才更新Memo,防止无效刷新。

代码片段示例:

private
  FLastClipboardText: string;

procedure TForm1.Timer1Timer(Sender: TObject);
var
  CurrentText: string;
begin
  if TClipboard.Current.HasText then
  begin
    CurrentText := TClipboard.Current.GetText;
    if CurrentText <> FLastClipboardText then
    begin
      FLastClipboardText := CurrentText;
      Memo1.Text := CurrentText;
    end;
  end
  else
    FLastClipboardText := '';
end;

方案对比

  • 原生监听:实时性强、系统开销低,是最优方案,但需维护平台特定代码;
  • TTimer轮询:实现简单、无需平台适配,适合快速开发,但实时性依赖轮询间隔。

内容的提问来源于stack exchange,提问作者Mike Stephenson

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.14 14:27:42