控件的所有者和父级之间有什么区别?

A B*_*A B 10 delphi delphi-7

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

每个组件有2种性质OwnerParent在运行时.谁能帮助我理解两者之间的区别?它们如何被windows用于显示控件或表单?

Dav*_*nan 25

所有者

Owner是介绍的属性TComponent,Owner本身也有类型TComponent.它Owner主要用于管理设计组件的生命周期.也就是说,您放置在表单设计器(或实际上是其他设计表面)上的组件,其生命周期完全由框架管理.该文件说:

指示负责流式传输和释放此组件的组件.

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

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

这有很多细微差别:

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

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

constructor Create(AOwner: TComponent); virtual;
Run Code Online (Sandbox Code Playgroud)

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

值得指出的是,Win32有一个完全不同的窗口所有者概念,不应该与同名的VCL概念混淆.在Windows文档说:

拥有Windows

重叠或弹出窗口可以由另一个重叠或弹出窗口拥有.拥有在窗口上设置了几个约束. - 拥有的窗口始终位于z顺序的所有者之上. - 系统在其所有者被销毁时自动销毁拥有的窗口. - 当拥有者最小化时,隐藏拥有的窗口.

只有重叠或弹出窗口可以是所有者窗口; 子窗口不能是所有者窗口.

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

为了表明混淆是多么容易,VCL 文档说:

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

这是完全错误的.对于顶级窗口,这是所有者而不是父级.

Parent是一个定义的属性TControl,具有类型TWinControl.广义上,此属性用于公开父控件和子控件的Win32概念.在Windows文档说:

窗口可以有父窗口.具有父级的窗口称为子窗口.父窗口提供用于定位子窗口的坐标系.父窗口会影响窗口外观的各个方面; 例如,剪切子窗口,以便子窗口的任何部分都不会出现在其父窗口的边框之外.没有父窗口或父窗口是桌面窗口的窗口称为顶级窗口.

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

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

请注意,当一个窗口控件(即TWinControl后代)被销毁时,它也会销毁它的所有子节点.

一个TWinControl后代可以枚举使用它的孩子ControlCountControls[]性能.这些枚举了窗口和非窗口的子项.