控件的所有者和父级有啥区别?
Posted
技术标签:
【中文标题】控件的所有者和父级有啥区别?【英文标题】:What is the difference between Owner and Parent of a control?控件的所有者和父级有什么区别? 【发布时间】:2015-11-21 09:06:37 【问题描述】:我对 Delphi VCL 控件的两个属性有点好奇。
每个组件在运行时都有 2 个属性,分别是 Owner
和 Parent
。谁能帮我理解两者之间的区别?窗口如何使用它们来显示控件或表单?
【问题讨论】:
将一个表单的Parent
设置为另一个表单,你会看到;-)
【参考方案1】:
所有者
Owner
是TComponent
中引入的属性,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 属性相同。
这是完全错误的。对于***窗口,这是所有者而不是父窗口。
家长
Parent
是TControl
中定义的属性,类型为TWinControl
。此属性广泛用于公开父控件和子控件的 Win32 概念。 Windows documentation 说:
一个窗口可以有一个父窗口。有父窗口的窗口称为子窗口。父窗口提供用于定位子窗口的坐标系。拥有父窗口会影响窗口外观的各个方面;例如,一个子窗口被剪裁,这样子窗口的任何部分都不能出现在其父窗口的边界之外。没有父窗口或父窗口是桌面窗口的窗口称为***窗口。
本质上,VCL Parent
属性直接映射到 Win32 父概念。
但是请注意,Parent
是在 TControl
中定义的。现在,TControl
没有窗口化,所以 TControl
不是 Win32 意义上的子控件,因为 Win32 窗口的子窗口本身就是窗口。因此,带有已定义Parent
的TControl
是VCL 意义上的子控件,称为非窗口子控件。这些非窗口控件将自己绘制为父级绘制处理程序的一部分。这种控件的典型示例是TLabel
。
请注意,当一个窗口控件(即 TWinControl
后代)被销毁时,它也会销毁其所有子项。
TWinControl
后代可以使用 ControlCount
和 Controls[]
属性枚举其子代。这些枚举窗口和非窗口的孩子。
【讨论】:
内容丰富!我一直在为育儿系统苦苦挣扎,而 Delphi 的手册根本没有帮助。以上是关于控件的所有者和父级有啥区别?的主要内容,如果未能解决你的问题,请参考以下文章