Delphi破坏父表单的动态控制onDestroy

时间:2015-03-07 03:16:41

标签: delphi

如何确保动态控件与其父窗体一起被销毁?

因此,从主窗体中,我为辅助表单创建了一个按钮,然后我显示了辅助表单上的按钮。

现在,我想确保创建的按钮与辅助表单一起销毁。

是否足以制作按钮的父级,次要形式?会这样做吗?

我正在使用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;

3 个答案:

答案 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;行放置一个断点。在调试器中运行您的应用程序,并确保代码在断点处停止。即。

  • 打开您的子表单。
  • 销毁您的子表单。 (强调销毁,因为如果CloseActioncaHide,只需关闭表单就不足以进行测试。)
  • 确认您已到达断点。
  • F9 继续运行。
  • 同时验证每个按钮只能到达断点一次。 (否则会出现双重破坏错误,可能导致访问冲突和不可预测的行为。)

您还可以在编译器选项中启用Debug DCU。然后当你点击断点时检查调用堆栈 Ctrl + Alt + S ,看看你的按钮被摧毁的VCL代码在哪里。