我想问一下,当我复制一个控件时,如何保留控件之间的联系。例如,我有一个编辑框,可以用滑块控制数值的变化,当我使用这段代码复制时,我实现了项目的复制,但滑块停止控制编辑框的数值。
TypInfo;
procedure CloneProperties(const Source: TControl; const Dest: TControl);
var
ms: TMemoryStream;
OldName: string;
begin
OldName := Source.Name;
Source.Name := ''; // needed to avoid Name collision
try
ms := TMemoryStream.Create;
try
ms.WriteComponent(Source);
ms.Position := 0;
ms.ReadComponent(Dest);
finally
ms.Free;
end;
finally
Source.Name := OldName;
end;
end;
procedure CloneEvents(Source, Dest: TControl);
var
I: Integer;
PropList: TPropList;
begin
for I := 0 to GetPropList(Source.ClassInfo, [tkMethod], @PropList) - 1 do
SetMethodProp(Dest, PropList[I], GetMethodProp(Source, PropList[I]));
end;
procedure DuplicateChildren(const ParentSource: TWinControl;
const WithEvents: Boolean = True);
var
I: Integer;
CurrentControl, ClonedControl: TControl;
begin
for I := ParentSource.ControlCount - 1 downto 0 do
begin
CurrentControl := ParentSource.Controls[I];
ClonedControl := TControlClass(CurrentControl.ClassType).Create(CurrentControl.Owner);
ClonedControl.Parent := ParentSource;
CloneProperties(CurrentControl, ClonedControl);
ClonedControl.Name := CurrentControl.Name + '_';
if WithEvents then
CloneEvents(CurrentControl, ClonedControl);
end;
end;
procedure TForm1.Button1Click(Sender: TObject);
begin
DuplicateChildren(Panel1);
end;
除非我误解了你的意思,否则你的CloneProperties似乎与你所问的问题没有任何关系。 在你的例子中,一个编辑控件E1和一个滑块S1,你可以克隆它们两个来产生E2和S2,但是在你的代码中的某个地方必须有一条语句,根据S1的值来改变E1的值。 然而,在你很可能写的方式中,该语句并不适用于E2和S2。
最简单的方法是写一个方法,它接受组件实例,并将这两个实例的操作联系在一起。
procedure TForm1.SetEditControlFromSlider(AnEdit : TEdit; ASlider : { TWhatever the slider actually is);
begin
// Set AnEdit's value from ASlider's properties
end;
然后,你可以像这样用EditSlider对来调用这个方法
SetEditControlFromSlider(E1, S1);
[...]
SetEditControlFromSlider(E2, S2);
我可以想象你可能不喜欢这样做。
IMO,最干净的解决方案是完全避免尝试克隆组件,并创建一个包含Edit、Slider和连接它们的代码的TFrame,然后根据你的需要添加到你的表单中的框架实例。 这就像从一根木头上掉下来一样简单。
type
TEditFrame = class(TFrame) // needs to be in its own unit, Used by your form
Edit1: TEdit;
TrackBar1: TTrackBar;
procedure TrackBar1Change(Sender: TObject);
private
public
end;
[...]
procedure TEditFrame.TrackBar1Change(Sender: TObject);
begin
Edit1.Text := IntToStr(TrackBar1.Position)
end;
然后,你可以通过以下方式将框架的克隆添加到TForm1中。
procedure TForm1.Button1Click(Sender: TObject);
var
AFrame : TEditFrame;
begin
Inc(FrameCount); // Field of TForm1
AFrame := TEditFrame.Create(Self);
AFrame.Name := AFrame.Name + IntToStr(FrameCount);
AFrame.Parent := Self;
AFrame.Top := AFrame.Height * FrameCount;
end;
请注意,因为连接这两个组件的代码。TrackBar1Change
它被编译到框架的单元中,它被你创建的每一个框架实例自动共享,不需要 "克隆 "代码。