控件的所有者和父级有啥区别?

Posted

技术标签:

【中文标题】控件的所有者和父级有啥区别?【英文标题】:What is the difference between Owner and Parent of a control?控件的所有者和父级有什么区别? 【发布时间】:2015-11-21 09:06:37 【问题描述】:

我对 Delphi VCL 控件的两个属性有点好奇。

每个组件在运行时都有 2 个属性,分别是 OwnerParent。谁能帮我理解两者之间的区别?窗口如何使用它们来显示控件或表单?

【问题讨论】:

将一个表单的Parent 设置为另一个表单,你会看到;-) 【参考方案1】:

所有者

OwnerTComponent 中引入的属性,Owner 本身具有TComponent 类型。 Owner 主要用于管理设计组件的生命周期。也就是说,您放置在表单设计器(或实际上是其他设计表面)上并且其生命周期完全由框架管理的组件。 documentation 说:

指示负责流式传输和释放该组件的组件。

创建表单时,流框架会解析 .dfm 文件并实例化其中列出的组件。这些组件创建时通常使用Owner 指定为表单。

组件生命的另一端是破坏。当一个组件被销毁时,它也会销毁它拥有的所有组件。考虑一个具体的例子,一个位于TForm 上的TButton,在设计时放置在那里。流框架创建按钮,将其Owner 设置为表单。作为TComponent 的后代,表单维护了它拥有的所有组件的列表。当表单被销毁时,它会遍历该拥有组件的列表并销毁它们。按钮就是这样销毁的。

这有很多细微差别:

组件不需要为表单所有。例如,在运行时创建的组件归您传递给构造函数的任何组件所有。 组件不需要拥有所有者,您可以将nil 传递给构造函数。在这种情况下,程序员仍然负责销毁组件。 所有权可以在组件的生命周期内更改。

因为流式框架实例化了组件,所以TComponent的构造函数被声明为virtual:

constructor Create(AOwner: TComponent); virtual;

如果您从TComponent 后代派生,并且希望将该派生组件放置在设计图面上,那么您必须尊重此虚拟构造函数。如果您在 TComponent 后代中定义构造函数,则它必须覆盖此虚拟构造函数。

值得指出的是,Win32 对窗口所有者的概念完全不同,不应与同名的 VCL 概念混淆。 Windows documentation 说:

自有 Windows

重叠或弹出窗口可以由另一个重叠或弹出窗口拥有 弹出窗口。拥有对一个窗口有几个限制。 - 拥有的窗口在 z 顺序中始终位于其所有者之上。 - 当所有者被销毁时,系统会自动销毁拥有的窗口。 - 拥有的窗口在其所有者最小化时被隐藏。

只有重叠的或弹出的窗口可以是所有者窗口;一个孩子 窗口不能是所有者窗口。

在 VCL 术语中,此概念由 PopupParent 属性公开。该属性是在 Delphi 7 之后引入的,因此您将无法使用。在 Delphi 7 中,框架设置了窗口所有者,并且没有提供简单的机制来覆盖框架的选择。如果您确实需要影响窗口所有权,那么您必须覆盖CreateParams 并设置Params.WndParent。不幸的是,在 Delphi 7 中,VCL 对所有权的处理存在许多问题,有时需要仔细研究这些有些血腥的细节。

VCL documentation 表示:

WndParent:父窗口的窗口句柄。这与父控件的 Handle 属性相同。

这是完全错误的。对于***窗口,这是所有者而不是父窗口。

家长

ParentTControl 中定义的属性,类型为TWinControl。此属性广泛用于公开父控件和子控件的 Win32 概念。 Windows documentation 说:

一个窗口可以有一个父窗口。有父窗口的窗口称为子窗口。父窗口提供用于定位子窗口的坐标系。拥有父窗口会影响窗口外观的各个方面;例如,一个子窗口被剪裁,这样子窗口的任何部分都不能出现在其父窗口的边界之外。没有父窗口或父窗口是桌面窗口的窗口称为***窗口。

本质上,VCL Parent 属性直接映射到 Win32 父概念。

但是请注意,Parent 是在 TControl 中定义的。现在,TControl 没有窗口化,所​​以 TControl 不是 Win32 意义上的子控件,因为 Win32 窗口的子窗口本身就是窗口。因此,带有已定义ParentTControl 是VCL 意义上的子控件,称为非窗口子控件。这些非窗口控件将自己绘制为父级绘制处理程序的一部分。这种控件的典型示例是TLabel

请注意,当一个窗口控件(即 TWinControl 后代)被销毁时,它也会销毁其所有子项。

TWinControl 后代可以使用 ControlCountControls[] 属性枚举其子代。这些枚举窗口和非窗口的孩子。

【讨论】:

内容丰富!我一直在为育儿系统苦苦挣扎,而 Delphi 的手册根本没有帮助。

以上是关于控件的所有者和父级有啥区别?的主要内容,如果未能解决你的问题,请参考以下文章

定位的区别

如果父级有类,则流星渲染模板

Unity3D - “父级有一种布局组”错误

有两个div,一个父级,一个子级,父级有滚动条,样式如何写才能让子级的div固定在顶部,不随滚动条

根目录,当前目录,和父级目录在node中写法需要注意的地方

完整的二叉树交换子级和父级错误