如何确保动态控件与其父窗体一起被销毁?
因此,从主窗体中,我为辅助表单创建了一个按钮,然后我显示了辅助表单上的按钮。
现在,我想确保创建的按钮与辅助表单一起销毁。
是否足以制作按钮的父级,次要形式?会这样做吗?
我正在使用TButton类的自定义后代 - TMyButton。所以在我的构造函数中,我有下一个代码:
constructor TMyButton.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
Self.OnClick := Self.MyButtonClick;
Self.Parent:=TWinControl(AOwner);
self.Visible := true;
end;
这样可以吗? 它适用于我,它不会抛出任何错误,但我想确保所述按钮与它所放置的表格一起被销毁。
MyButton将被放置在辅助表格上,让我们说“Form2' 所以会有一个代码:
var
bt:TMyButton;
begin
bt:=TMyButton.Create(Form2);
bt.Parent:=Form2;
...
form2.Show;
end;
答案 0 :(得分:4)
首先:setting a control's parent in its constructor is wrong!对于在设计时创建的控件,IDE将负责设置父级。对于在运行时创建的控件,创建代码应负责设置父级。
如何确保动态控件与其父窗体一起销毁?
具有父级的控件将在销毁该直接父级时自动销毁。此外,具有所有者的控件将在该所有者被销毁时自动销毁。它是所有者在控件的父链中然后一切都很好。如果所有者不在控件的父链中,那么您的设计问题可能会导致意外破坏。
您当前的构造函数完全没必要。将所有者(可以是零!)转换为TWinControl
而不进行检查是错误的。但正如所说,设置父母不应该在那里。默认情况下,Visible为true,并且分配OnClick
事件将阻止其进一步使用。相反,覆盖Click
。
关于您的评论,调用代码将变为:
procedure TForm1.Button1Click(Sender: TObject);
var
Button: TButton;
begin
Button := TButton.Create(Form2);
Button.OnClick := Form2.ButtonClick;
Button.SetBounds(10, 10, 75, 25);
Button.Parent := Form2;
end;
但这使你没有参考按钮。而是将变量添加到更高的范围。
答案 1 :(得分:1)
使用此代码,您不应该遇到问题。
您要让所有者和父母都是子表单。所以当发布表格时。这将释放它包含的对象。
我将解释父母和所有者之间的区别: 分配父项时,表示“可视容器”。显示的对象是......一个面板,一个框架。
此外,业主是业主。对象所有者有责任释放所有对象“奴隶”。
通常,Parent和Owner都是相同的,因为我们自动设计接口并可视化地放置组件。 当你想在运行时创建可视组件时,必须很好地控制谁是Parent,以及所有者。
不同的是,如果你在所有者中设置Nil:
Obj := TObject.Create(nil);
如果您必须指明何时应该释放它。这是你的责任。
编辑: 你可以使用TButton。像这样:
procedure TForm1.CreateButton;
var obj: TButton;
begin
obj := TButton.Create(Form2);
obj.Parent := Form2;
Obj.OnClick := MyEventOnClick;
end;
编辑2:
Zarko Gajic,在About.com上有一篇很好的文章值得一读。
这有助于补充您提供的内容。您可以在http://delphi.about.com/od/objectpascalide/a/owner_parent.htm
中查看该文章答案 2 :(得分:1)
简短的回答是:是的,您的按钮将随表格一起销毁 但如果您知道如何自己验证这一点,将会很有用。
编写以下代码: (注意:不要忘记声明方法的覆盖。)
destructor TMyButton.Destroy;
begin
inherited Destroy;
end;
现在在inherited Destroy;
行放置一个断点。在调试器中运行您的应用程序,并确保代码在断点处停止。即。
CloseAction
是caHide
,只需关闭表单就不足以进行测试。)您还可以在编译器选项中启用Debug DCU。然后当你点击断点时检查调用堆栈 Ctrl + Alt + S ,看看你的按钮被摧毁的VCL代码在哪里。