|
15番会議室「FAQ編纂委員会」に寄せられた「よくある質問の答え」
[Q]
オブジェクトをコピーしたいのですが,やりかたがわかりません。
[A]
クラス型変数は実はオブジェクトへのポインタです。変数同士で代入しても
ポインタのコピーになって実体はコピーされませんので,別途生成してから
コピーしたいプロパティやメンバを一つづつ代入することが必要です。
なお,オブジェクトの中にはAssignメソッドを持つものもあって,
このメソッドを使うとたいてい望みのコピー動作をしてくれますが,
コピーされないプロパティもあるので,よく注意して使います。
TComponent用にすべてのpublishedプロパティのコピーを自動的に
やる手続きを例としてあげておきますので,ビジュアルコンポ
についてはこれを使うと手間が省けます。ただしイベントはコピー
しません。
[例]
フォームにパネルを一個とパネルの上にTEditを一個貼り付けて
ください。パネルのMouseUpイベントを作ってアタッチして下さい。
パネルをクリックすると次々にコピーされます。
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
StdCtrls, ExtCtrls;
type
TForm1 = class(TForm)
Panel1: TPanel;
Edit1: TEdit;
procedure Panel1MouseUp(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
end;
var
Form1: TForm1;
implementation
{$R *.DFM}
///////////汎用コンポーネントコピー手続き////////////
// DestがnilならSrcと同じクラスで自動生成して返す
// nilでなければ中身をコピーして返す
// 子コントロールも一緒にコピーされる
procedure CopyComponent(const Src: TComponent; var Dest: TComponent);
// できたコンポにデフォルトの名前をつける
procedure SetValidName(Compo: TComponent);
var NewName: string;
i: integer;
begin
if Compo.Owner = nil then Exit;
with Compo do begin
i := 0;
repeat
inc(i);
NewName := ClassName + IntToStr(i);
Delete(NewName,1,1);
until Owner.FindComponent(NewName) = nil;
Name := NewName;
end;
end;
// コンポのクラスをシステムのリストに登録
procedure RegisterChildClass(Component: TComponent);
var i:integer;
begin
if GetClass(Component.ClassName) = nil then begin
RegisterClass(TPersistentClass(Component.ClassType));
end;
if not(Component is TWinControl) then Exit;
with TWinControl(Component) do begin
for i := 0 to ControlCount-1 do begin
RegisterChildClass(Controls[i]); // recursive call
end;
end;
end;
var Stream: TMemoryStream;
SrcName: string;
i,Count: integer;
ChildCompo: TComponent;
begin
Stream := TMemoryStream.Create;
try
SrcName := Src.Name;
Src.Name := '';
RegisterChildClass(Src);
if Dest = nil then begin
Dest := TComponentClass(Src.ClassType).Create(Src.Owner);
end;
with Stream do begin
WriteComponent(Src);
Seek(0,0);
ReadComponent(Dest);
end;
if Dest is TControl then begin
TControl(Dest).Parent := nil;
end;
Src.Name := SrcName;
if Dest.ComponentCount <> 0 then begin
SetValidName(Dest);
with Dest do begin
Count := ComponentCount;
for i := 0 to Count-1 do begin
ChildCompo := Components[0];
ChildCompo.Name := '';
RemoveComponent(ChildCompo);
Owner.InsertComponent(ChildCompo);
SetValidName(ChildCompo);
end;
end;
end;
finally
Stream.Free;
end;
end;
procedure TForm1.Panel1MouseUp(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
var Cre,Org: TControl;
NewPt: TPoint;
begin
Org := TControl(Sender);
Cre := nil;
// コンポーネントのコピー
CopyComponent(Org, TComponent(Cre));
NewPt := Org.ClientToScreen( Point(0, 0) );
NewPt := Self.ScreenToClient(NewPt);
with TPanel(Cre) do begin
Left := NewPt.X +10;
Top := NewPt.Y + 10;
Parent := Self;
OnMouseUp := Panel1MouseUp;
end;
end;
end.
ここにあるドキュメントは NIFTY SERVEの Delphi Users' Forum FDELPHIに寄せられる質問の中から、よくある質問への回答を FDELPHIのメンバーがまとめたものです。 したがって、これらの回答はボーランド株式会社がサポートする公式のものではなく、掲示されている内容についての問い合わせは受けられない場合があります。
Copyright 1996-1998 Delphi Users' ForumFAQ編纂委員会
|