各位大哥,如何实现在运行期间在form上复制控件的功能阿,分不够再加!(200分)

  • 主题发起人 主题发起人 linninbo
  • 开始时间 开始时间
L

linninbo

Unregistered / Unconfirmed
GUEST, unregistred user!
我写了一个用户表单定制的程序,实现的动态控件的创建,移动,删除,保存等功能
可是如何实现控件的复制呢?比如说用户在form上动态创建了一个label或者button,当复制这些控件时,新的组件要求和原先的的属性相同。不知如何实现,另外,我这些用来动态创建组件的类已经全部继承重写了,例如
type
Cbutton=class(Tbutton)
......
这样好方便我控制初始化的状态在控件里。
感谢阿!
 
创建好了用assign方法复制属性就可以了。
 
你可以学学 delphi 的方法;
delphi 复制时用的
把一个控件的类和属性用 文本的方法表示. 就像 *.dfm 里面 一样.
例如:
复制一个button ,后 他是这样保存在 clipboard 里面的

button:=tbutton
top:=1
left=2
caption:=''
..........

 
参考一下吧,

unit CloneComponents;

interface
uses
Classes;

function CloneComponent(aSource: TComponent): TComponent;

implementation
uses
SysUtils, Controls;

type
TComponentReader = class(TReader)
public
Component: TComponent;
procedure Read(aComponent: TComponent);
procedure GetName(Reader: TReader; Component: TComponent; var Name: String);
end;

procedure TComponentReader.Read(aComponent: TComponent);
begin
Component := aComponent;
end;

procedure TComponentReader.GetName(Reader: TReader; Component: TComponent; var Name: String);
var
I : Integer;
Tempname: String;
begin
I := 0;
Tempname := Name;
//确保控件Name属性唯一
while Component.Owner.FindComponent(Name) <> nil do
begin
Inc(I);
Name := Format('%s%d', [Tempname, I]);
end;
end;

function CloneComponent(aSource: TComponent): TComponent;
procedure RegisterComponentClasses(aComponent: TComponent);
var
I : Integer;
begin
RegisterClass(TPersistentClass(aComponent.ClassType));
if aComponent is TWinControl then
begin
for I := 0 to (TWinControl(aComponent).ControlCount-1) do
begin
RegisterComponentClasses(TWinControl(aComponent).Controls);
end;
end;
end;

var
Stream : TMemoryStream;
Reader : TComponentReader;
Writer : TWriter;
begin
Stream := TMemoryStream.Create;
try
RegisterComponentClasses(aSource);

Writer := TWriter.Create(Stream, 4096);
try
Writer.Root := aSource.Owner;
Writer.WriteSignature;
Writer.WriteComponent(aSource);
Writer.WriteListEnd;
finally
Writer.Free;
end;

Stream.Position := 0;
Reader := TComponentReader.Create(Stream, 4096);
try
with Reader do
begin
OnSetName := getName; //生成唯一名称
Component := nil;

if aSource is TWinControl then
begin
ReadComponents(TWinControl(aSource).Owner, TWinControl(aSource).Parent, Read);
end
else
begin
ReadComponents(aSource.Owner, nil, Read);
end;
Result := Component;
end;
finally
Reader.Free;
end;
finally
Stream.Free;
end;
end;

end.
 
object Form1: TForm1
Left = 156
Top = 124
Width = 791
Height = 543
Caption = 'Form1'
Color = clBtnFace
Font.Charset = DEFAULT_CHARSET
Font.Color = clWindowText
Font.Height = -13
Font.Name = 'MS Sans Serif'
Font.Style = []
OldCreateOrder = False
OnCreate = FormCreate
PixelsPerInch = 120
TextHeight = 16
object Label1: TLabel
Left = 296
Top = 296
Width = 3
Height = 16
end
object GroupBox1: TGroupBox
Left = 0
Top = 0
Width = 273
Height = 241
Caption = '测试区'
TabOrder = 0
object Button1: TButton
Left = 16
Top = 24
Width = 75
Height = 25
Caption = '测试按钮'
TabOrder = 0
OnClick = Button1Click
end
object Memo1: TMemo
Left = 120
Top = 24
Width = 129
Height = 145
Lines.Strings = (
'这是一个例子')
TabOrder = 1
OnClick = Memo1Click
end
end
object StringGrid1: TStringGrid
Left = 507
Top = 8
Width = 246
Height = 489
ColCount = 2
DefaultColWidth = 100
FixedRows = 0
TabOrder = 1
end
object ListBox1: TListBox
Left = 280
Top = 64
Width = 209
Height = 433
ItemHeight = 16
TabOrder = 2
end
object Button2: TButton
Left = 280
Top = 8
Width = 209
Height = 25
Caption = 'to Component'
Enabled = False
TabOrder = 3
OnClick = Button2Click
end
object GroupBox2: TGroupBox
Left = 0
Top = 240
Width = 273
Height = 257
Caption = '新控件'
TabOrder = 4
end
end


unit Unit1;

interface

uses
Windows, WinTypes, WinProcs, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
Grids, StdCtrls;

type
TForm1 = class(TForm)
GroupBox1: TGroupBox;
Button1: TButton;
Memo1: TMemo;
StringGrid1: TStringGrid;
ListBox1: TListBox;
Button2: TButton;
GroupBox2: TGroupBox;
Label1: TLabel;
procedure FormCreate(Sender: TObject);
procedure Button1Click(Sender: TObject);
procedure Memo1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
procedure ShowComponents(Components:TComponent);
function StringToComponent(Value: string;Parent:TWinControl;Owner:TComponent): TComponent;

end;

var
Form1: TForm1;

implementation

{$R *.DFM}

procedure TForm1.FormCreate(Sender: TObject);
var
i:integer;
begin
StringGrid1.Cells[0,0]:='名称';
StringGrid1.Cells[0,1]:='类型';

end;



procedure TForm1.ShowComponents(Components: TComponent);
var
strBin:TMemoryStream;
StrTxt:TStringStream;
s:String;
i,Rows:Integer;
List:TStringList;
begin
strTxt:=TStringStream.Create(s) ; //一个字符流
strBin:=TMemoryStream.Create ; //一个二进制流
List:=TStringList.Create;
try
StrBin.WriteComponent(Components); //读组件
StrBin.Seek (0,soFromBeginning); //把指针放回流的起始位置,否则读不到东西
ObjectBinaryToText(StrBin,StrTxt); //把二进制流换成字符流
strTxt.Seek (0,soFromBeginning);
List.Text :=strTxt.DataString; // 把字符流赋给List
ListBox1.items.Text :=strTxt.DataString;
finally
strBin.Free ;
strTxt.Free ;
end;
//循环添入值
Rows:=List.Count ;
StringGrid1.RowCount :=Rows;
s:=List.Strings [0];
StringGrid1.Cells[1,0]:=copy(s,pos(' ',s)+1,pos(':',s)-pos(' ',s)-1);
StringGrid1.Cells[1,1]:=copy(s,pos(':',s)+1,Length(s)-pos(':',s));
for i:=1 to Rows-1 do
begin
s:=List.Strings ;
StringGrid1.Cells[1,i+1]:=Copy(s,Pos('=',s)+1,Length(s)-pos(':',s));
StringGrid1.Cells[0,i+1]:=Copy(s,1,Pos('=',s)-1);
end;
//StrTxt.Free ;
//StrBin.Free ;
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
ShowComPonents(Button1);
Button2.Enabled :=True;
end;

procedure TForm1.Memo1Click(Sender: TObject);
begin
ShowComPonents(Memo1);
Button2.Enabled :=True;
end;

function Tform1.StringToComponent(Value: string;Parent:TWinControl;Owner:TComponent): TComponent;
var
StrStream:TStringStream;
BinStream: TMemoryStream;
MyReader:TReader;
begin
StrStream := TStringStream.Create(Value);
try
BinStream := TMemoryStream.Create;
try
StrStream.Seek(0, soFromBeginning);//一定要有
ObjectTextToBinary(StrStream, BinStream);
BinStream.Seek(0, soFromBeginning);
MyReader:=TReader.Create (BinStream,BinStream.Size);
MyReader.Parent :=Parent;
MyReader.Owner:=owner;
result:=MyReader.ReadRootComponent(nil);
MyReader.Free ;
finally
BinStream.Free;
end;
finally
StrStream.Free;
end;
end;

procedure TForm1.Button2Click(Sender: TObject);
var
bb:TComponent;
begin
bb:=StringToComponent(ListBox1.Items.Text,GroupBox2,GroupBox2);
InsertComponent(bb);
Button2.Enabled :=False;
end;

initialization

RegisterClasses ([TButton, TMemo]);


end.

 
用assign 不行阿
 
多人接受答案了。
 
后退
顶部