Clipboard.SetComponent 默認只序列化組件本身。若容器組件(如 TPanel)包含子控件(TEdit、TButton 等),直接複製面板不會帶上子控件。解決方案:創建自定義容器類,在構造函數中內建子控件,並註冊類,使流式系統識別完整對象圖。
WriteComponent/ReadComponent 序列化/反序列化。RegisterClasses 註冊表實例化對象。.dfm 流中包含子組件的屬性數據,前提是子組件被父組件擁有(Owner := Self)。MyPanel.pasunit MyPanel;
interface
uses
Classes, StdCtrls, ExtCtrls;
type
TMyPanel = class(TPanel)
private
FEdit: TEdit;
public
constructor Create(AOwner: TComponent); override;
destructor Destroy; override;
property Edit: TEdit read FEdit;
end;
implementation
constructor TMyPanel.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
// 內建子控件,關鍵:Owner := Self,Parent := Self
FEdit := TEdit.Create(Self);
FEdit.Parent := Self;
FEdit.SetBounds(10, 10, 150, 24);
FEdit.Text := '隨面板複製';
// 註冊類,讓流式系統能按類名實例化
RegisterClasses([TMyPanel]);
end;
destructor TMyPanel.Destroy;
begin
// FEdit 由 Owner 釋放,無需手動 Free
inherited;
end;
end.
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, Clipbrd, MyPanel;
type
TForm1 = class(TForm)
btnCopy: TButton;
btnPaste: TButton;
procedure FormCreate(Sender: TObject);
procedure btnCopyClick(Sender: TObject);
procedure btnPasteClick(Sender: TObject);
private
FPanel: TMyPanel;
FPastedObj: TComponent;
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
procedure TForm1.FormCreate(Sender: TObject);
begin
// 創建自定義面板實例
FPanel := TMyPanel.Create(Self);
FPanel.Parent := Self;
FPanel.SetBounds(20, 20, 200, 100);
FPanel.Caption := '源面板';
FPanel.Edit.Text := '一起被複製的編輯框';
btnCopy.Caption := '複製面板';
btnPaste.Caption := '粘貼副本';
btnPaste.Left := 120;
end;
procedure TForm1.btnCopyClick(Sender: TObject);
begin
Clipboard.SetComponent(FPanel);
ShowMessage('面板及其子控件已放入剪貼簿');
end;
procedure TForm1.btnPasteClick(Sender: TObject);
var
NewPanel: TMyPanel;
begin
if not Clipboard.HasFormat(CF_COMPONENT) then Exit;
// GetComponent(Owner, Parent) 返回新組件
FPastedObj := Clipboard.GetComponent(Self, Self);
if not Assigned(FPastedObj) then Exit;
NewPanel := FPastedObj as TMyPanel;
// 避免重疊,稍微偏移
NewPanel.SetBounds(FPanel.Left + 30, FPanel.Top + 50, FPanel.Width, FPanel.Height);
NewPanel.Caption := '副本_' + IntToStr(Random(1000));
NewPanel.Edit.Text := '我是副本的編輯框';
end;
initialization
// 關鍵:確保 TMyPanel 在流式系統中可被識別
RegisterClasses([TMyPanel]);
end.
RegisterClasses 的時機與位置initialization 區塊。保證單元被引用時自動註冊,無需調用方記憶。FormCreate、initialization 多處出現。EClassNotFound「Class not found: TMyPanel」。| 屬性 | 作用 | 複製行為 |
|---|---|---|
| Owner | 生命週期管理,析構時釋放 | 流式存儲必須,決定組件樹結構 |
| Parent | 視覺包含、座標系、訊息路由 | 不存儲,粘貼時由 GetComponent 的 AParent 參數指定 |