控件的所有者和父级之间有什么区别?
What is the difference between Owner and Parent of a control?
我对Delphi VCL 控件的两个属性有点好奇。
每个组件在运行时有 2 个属性 Owner
和 Parent
。任何人都可以帮助我理解两者之间的区别吗? windows 如何使用它们来显示控件或表单?
所有者
Owner
is a property introduced in TComponent
, and Owner
itself has type TComponent
. The Owner
is used primarily to manage the lifetime of designed components. That is, components that you place on the form designer (or indeed other design surfaces) and whose lifetime is managed entirely by the framework. The documentation 说:
Indicates the component that is responsible for streaming and freeing this component.
创建表单后,流式处理框架会解析 .dfm 文件并实例化其中列出的组件。这些组件通常使用指定为表单的 Owner
创建。
组件生命的另一端是销毁。当一个组件被销毁时,它也会销毁它拥有的所有组件。举个具体的例子,考虑一个 TButton
位于 TForm
上,在设计时放置在那里。流式框架创建按钮,将其 Owner
设置为表单。作为 TComponent
的后代,表单维护着它拥有的所有组件的列表。当表单被销毁时,它遍历拥有的组件列表并销毁它们。按钮就这样销毁了。
这有很多细微差别:
- 组件不需要由表单拥有。例如,在 运行 时间创建的组件归您传递给构造函数的任何组件所有。
- 组件无需拥有者,您可以将
nil
传递给构造函数。在这种情况下,程序员仍然负责销毁组件。
- 所有权可以在组件的生命周期内更改。
因为streaming framework实例化组件,TComponent
的构造函数被声明为virtual:
constructor Create(AOwner: TComponent); virtual;
如果您派生自 TComponent
后代,并且您希望将该派生组件放置在设计图面上,那么您必须遵守此虚拟构造函数。如果您在 TComponent
后代中定义一个构造函数,那么它必须覆盖此虚拟构造函数。
值得指出的是,Win32 对 window 的所有者有一个完全不同的概念,不应与同名的 VCL 概念相混淆。 Windows documentation 表示:
Owned Windows
An overlapped or pop-up window can be owned by another overlapped or
pop-up window. Being owned places several constraints on a window.
- An owned window is always above its owner in the z-order.
- The system automatically destroys an owned window when its owner is destroyed.
- An owned window is hidden when its owner is minimized.
Only an overlapped or pop-up window can be an owner window; a child
window cannot be an owner window.
在 VCL 术语中,这个概念由 PopupParent
属性 公开。 属性 是在 Delphi 7 之后引入的,因此您将无法使用。在 Delphi 7 中,框架设置了 window 所有者,并且没有提供简单的机制来覆盖框架的选择。如果您确实需要影响 window 所有权,那么您必须覆盖 CreateParams
并设置 Params.WndParent
。不幸的是,Delphi 7 中的 VCL 处理所有权存在许多问题,有时需要在这些有点血腥的细节中寻找。
为了说明混淆是多么容易,VCL documentation 说:
WndParent: The window handle of the parent window. This is the same as the Handle property of the parent control.
这是完全错误的。对于 top-level window,这是所有者而不是 parent。
Parent
Parent
is a property defined in TControl
and has type TWinControl
. This property is used, broadly, to expose the Win32 concept of parent and child controls. The Windows documentation 说:
A window can have a parent window. A window that has a parent is called a child window. The parent window provides the coordinate system used for positioning a child window. Having a parent window affects aspects of a window's appearance; for example, a child window is clipped so that no part of the child window can appear outside the borders of its parent window. A window that has no parent, or whose parent is the desktop window, is called a top-level window.
本质上,VCL Parent
属性 直接映射到 Win32 parent 概念。
但是请注意,Parent
是在 TControl
中定义的。现在,TControl
不是 windowed,所以 TControl
不是 Win32 意义上的 child 控件,因为 Win32 window 的 children 是他们自己 windows。因此,定义了 Parent
的 TControl
是 VCL 意义上的 child,称为 non-windowed child 控件。这些 non-windowed 控件将自身绘制为其 parent 的绘制处理程序的一部分。这种控件的典型示例是 TLabel
.
请注意,当 windowed 控件(即 TWinControl
后代)被销毁时,它也会销毁其所有 children。
A TWinControl
后代可以使用 ControlCount
和 Controls[]
属性枚举其 children。这些枚举 windowed 和 non-windowed children.
我对Delphi VCL 控件的两个属性有点好奇。
每个组件在运行时有 2 个属性 Owner
和 Parent
。任何人都可以帮助我理解两者之间的区别吗? windows 如何使用它们来显示控件或表单?
所有者
Owner
is a property introduced in TComponent
, and Owner
itself has type TComponent
. The Owner
is used primarily to manage the lifetime of designed components. That is, components that you place on the form designer (or indeed other design surfaces) and whose lifetime is managed entirely by the framework. The documentation 说:
Indicates the component that is responsible for streaming and freeing this component.
创建表单后,流式处理框架会解析 .dfm 文件并实例化其中列出的组件。这些组件通常使用指定为表单的 Owner
创建。
组件生命的另一端是销毁。当一个组件被销毁时,它也会销毁它拥有的所有组件。举个具体的例子,考虑一个 TButton
位于 TForm
上,在设计时放置在那里。流式框架创建按钮,将其 Owner
设置为表单。作为 TComponent
的后代,表单维护着它拥有的所有组件的列表。当表单被销毁时,它遍历拥有的组件列表并销毁它们。按钮就这样销毁了。
这有很多细微差别:
- 组件不需要由表单拥有。例如,在 运行 时间创建的组件归您传递给构造函数的任何组件所有。
- 组件无需拥有者,您可以将
nil
传递给构造函数。在这种情况下,程序员仍然负责销毁组件。 - 所有权可以在组件的生命周期内更改。
因为streaming framework实例化组件,TComponent
的构造函数被声明为virtual:
constructor Create(AOwner: TComponent); virtual;
如果您派生自 TComponent
后代,并且您希望将该派生组件放置在设计图面上,那么您必须遵守此虚拟构造函数。如果您在 TComponent
后代中定义一个构造函数,那么它必须覆盖此虚拟构造函数。
值得指出的是,Win32 对 window 的所有者有一个完全不同的概念,不应与同名的 VCL 概念相混淆。 Windows documentation 表示:
Owned Windows
An overlapped or pop-up window can be owned by another overlapped or pop-up window. Being owned places several constraints on a window. - An owned window is always above its owner in the z-order. - The system automatically destroys an owned window when its owner is destroyed. - An owned window is hidden when its owner is minimized.
Only an overlapped or pop-up window can be an owner window; a child window cannot be an owner window.
在 VCL 术语中,这个概念由 PopupParent
属性 公开。 属性 是在 Delphi 7 之后引入的,因此您将无法使用。在 Delphi 7 中,框架设置了 window 所有者,并且没有提供简单的机制来覆盖框架的选择。如果您确实需要影响 window 所有权,那么您必须覆盖 CreateParams
并设置 Params.WndParent
。不幸的是,Delphi 7 中的 VCL 处理所有权存在许多问题,有时需要在这些有点血腥的细节中寻找。
为了说明混淆是多么容易,VCL documentation 说:
WndParent: The window handle of the parent window. This is the same as the Handle property of the parent control.
这是完全错误的。对于 top-level window,这是所有者而不是 parent。
Parent
Parent
is a property defined in TControl
and has type TWinControl
. This property is used, broadly, to expose the Win32 concept of parent and child controls. The Windows documentation 说:
A window can have a parent window. A window that has a parent is called a child window. The parent window provides the coordinate system used for positioning a child window. Having a parent window affects aspects of a window's appearance; for example, a child window is clipped so that no part of the child window can appear outside the borders of its parent window. A window that has no parent, or whose parent is the desktop window, is called a top-level window.
本质上,VCL Parent
属性 直接映射到 Win32 parent 概念。
但是请注意,Parent
是在 TControl
中定义的。现在,TControl
不是 windowed,所以 TControl
不是 Win32 意义上的 child 控件,因为 Win32 window 的 children 是他们自己 windows。因此,定义了 Parent
的 TControl
是 VCL 意义上的 child,称为 non-windowed child 控件。这些 non-windowed 控件将自身绘制为其 parent 的绘制处理程序的一部分。这种控件的典型示例是 TLabel
.
请注意,当 windowed 控件(即 TWinControl
后代)被销毁时,它也会销毁其所有 children。
A TWinControl
后代可以使用 ControlCount
和 Controls[]
属性枚举其 children。这些枚举 windowed 和 non-windowed children.