首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> Delphi

Delphi 剪貼簿基礎 (3):組件複製粘貼(SetComponent/GetComponent)實戰

     編輯:Delphi

功能概覽

TClipboard.SetComponent/GetComponent 讓你在應用內或應用間以二進制組件流形式複製粘貼任意 VCL 組件(含屬性、子控件樹)。比文本/圖片格式強大得多,是構建可視化設計器、模板系統的核心 API。

核心 API 速查

方法類型說明
SetComponent(Component)過程將組件序列化放入剪貼簿(格式 CF_COMPONENT)
GetComponent(AOwner, AParent)函數反序列化並返回新組件實例
HasFormat(CF_COMPONENT)函數檢查剪貼簿是否包含組件格式

完整範例:Edit → Panel 複製粘貼

界面佈局

  • Edit1:源編輯框
  • Panel1:目標容器
  • btnCopy、btnPaste、btnDelete 三按鈕

代碼實現(優化版:初始化區註冊類)

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, ExtCtrls;

type
  TForm1 = class(TForm)
    Edit1: TEdit;
    Panel1: TPanel;
    btnCopy: TButton;
    btnPaste: TButton;
    btnDelete: TButton;
    procedure btnCopyClick(Sender: TObject);
    procedure btnPasteClick(Sender: TObject);
    procedure btnDeleteClick(Sender: TObject);
  private
    FPastedComponent: TComponent;
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

uses Clipbrd;

procedure TForm1.btnCopyClick(Sender: TObject);
begin
  // 一鍵放入剪貼簿
  Clipboard.SetComponent(Edit1);
  btnCopy.Caption := '已複製';
end;

procedure TForm1.btnPasteClick(Sender: TObject);
begin
  // 1. 格式檢查
  if not Clipboard.HasFormat(CF_COMPONENT) then Exit;

  // 2. 反序列化:Owner=Self(Form), Parent=Panel1
  FPastedComponent := Clipboard.GetComponent(Self, Panel1);
  if Assigned(FPastedComponent) then
  begin
    // 3. 微調位置避免重疊
    with FPastedComponent as TControl do
      SetBounds(Left + 20, Top + 20, Width, Height);
    btnPaste.Caption := '已粘貼';
  end;
end;

procedure TForm1.btnDeleteClick(Sender: TObject);
begin
  if Assigned(FPastedComponent) then
  begin
    FPastedComponent.Free; // 釋放副本
    FPastedComponent := nil;
    btnDelete.Caption := '已刪除';
  end;
end;

initialization
  // 關鍵:註冊 TEdit 類,否則 GetComponent 拋出 ClassNotFound
  RegisterClasses([TEdit]);

end.

關鍵技術細節

1. CF_COMPONENT:Delphi 專有格式

Windows 預定義格式(CF_TEXT、CF_BITMAP 等)不含組件流。CF_COMPONENT 是 Delphi 內部註冊的私有格式(RegisterClipboardFormat('Delphi Component')),僅 Delphi 應用間互通。

2. RegisterClasses 必須性

  • 流式系統按類名字串查找類引用實例化對象。
  • 未註冊 → EClassNotFound 異常。
  • 最佳實踐:在單元 initialization 區塊集中註冊,避免重複調用與遺漏。

3. GetComponent(AOwner, AParent) 參數詳解

4. 複製後的差異點

  • Name 自動重命名:Edit1 → Edit2 避免同名衝突。
  • 事件不複製:OnClick 等方法指針無法跨實例序列化,粘貼後為 nil。
  • 動態屬性保留:Text、Color、Font 等運行時修改的屬性完整保留。

進階:複製帶子控件的容器

參考前文(文章 9493),自定義 TMyPanel 內建 TEdit,註冊 TMyPanel 即可整體複製面板及其內部編輯框。

常見問題排查

參數傳值效果
AOwnerSelf (Form)新組件歸 Form 管理,Form 銷毀時自動釋放
AOwnernil需手動 Free,適合臨時對象
AParentPanel1新組件視覺掛載到 Panel1,座標相對 Panel1
AParentnil無父容器,需手動設 Parent 才可見
現象原因解決
粘貼後組件不可見AParent=nil 或 Parent 未設傳有效 Parent 或粘貼後手動 Parent := Panel1
ClassNotFound 異常忘記 RegisterClassesinitialization 區塊註冊所有涉及類
事件失效流式不保存方法指針粘貼後代碼重新綁定 OnClick 等
跨應用粘貼失敗目標應用未註冊相同類雙方共用組件單元或運行時包含相同類定義

總結

SetComponent/GetComponent 是 Delphi 組件級複製粘貼的「核武器」。掌握 註冊類、Owner/Parent 語義、格式檢查、事件重綁 四要素,即可構建強大的可視化編輯、模板復用、組件庫拖放等高級功能。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved