在运行时创建复合控件(其他控件的父级)

时间:2010-08-31 11:31:48

标签: delphi

我有一段代码,我覆盖了TStringGrid的inplace编辑器和提示窗口。为此,我基于TStringGrid创建了自己的字符串网格,并使用TEdit进行内部编辑,使用TPanel进行工具提示。在TMyStringGrid.Create构造函数中,我将它们初始化为:

Constructor TMyStringGrid.Create();
Begin
  inherited Create(AOwner);
  MyEditor:= TEdit.Create(Self);  
  MyEditor.Parent  := Self;
End;

在这种情况下,所有者(主窗体)正在释放控件。我用这个多年了,它起作用了。 问题在于,其他人认为程序员在实例化子控件时应使用NIL而不是Self,然后在Destroy析构函数中手动释放它们。似乎第二种替代方案比第一种替代方案具有巨大优势,特别是当您动态创建大量子控件时(不是我的情况)。他们说,我的代码的另一个问题是,在Application.ProcessMessages调用之后可能会释放子控件,而应用程序可能仍然想要使用它们。

那么,我应该让我的代码保持不变,还是应该手动创建并释放子控件? 有任何Borland复合控制的例子吗?


Delphi 7,Win XP
参考:http://delphi.about.com/od/kbcurt/ss/dynamiccreateno.htm

3 个答案:

答案 0 :(得分:3)

是的,您可以在不更改代码的情况下使用您的代码。

There is a any Borland example of compound controls?

最好的例子是检查TLabeledEdit的实现。

它是在构造函数

中创建标签
  if Assigned(FEditLabel) then exit;
  FEditLabel := TBoundLabel.Create(Self);
  FEditLabel.FreeNotification(Self);
  FEditLabel.FocusControl := Self;

答案 1 :(得分:2)

在这种情况下,没有充分的理由通过 nil 而不是Self。那个AOwner参数就是出于这个原因。利用它。

创建控件并手动销毁它时,有理由传递 nil ,但是对于完全不同的情况:如果您在函数内部创建控件(通常是表单)。这是一种非常常见的模式,例如:

MyDialog := TMyDialog.Create(nil);
try
  result := MyDialog.ShowModal;
finally
  MyDialog.Free;
end;

在那里,你想立即释放它,而不是等待当前的形式被破坏,这可能要晚得多。但是当谈到子组件时,通常希望它们与父组件同时销毁,而不是稍后,因此将Self传递给AOwner并让VCL为您处理它。

答案 2 :(得分:1)

考虑到构造函数,网格实例由Aowner拥有(它通常是TForm或TFrame)。 inplace编辑器由网格实例拥有并成为父级。我没有看到ProcessMessages如何导致子对象的破坏,因为它们将在TMyStringGrid的破坏循环中被销毁。那是 没有 我可以在该实现上看到错误 - 我对我创建的组件使用相同的设计。 VCL拥有所有权,以便在管理对象的生命周期时轻松生活。并且是将nil推荐为所有者的情况,这在Mason的回答中显示。

在Mason所示的模式中,NIL的原因是,如果没有所有者,对象销毁将不会进入Notification循环。如果您创建了许多手动处理的破坏组件,则需要确保所有者为NIL,否则会在每个组件构造/销毁中执行大量代码(不需要)。 许多月前,网络存档上有一篇优秀的白皮书(现已解散)eagle-software.com