解决方法
Owner
是TComponent中引入的属性,Owner本身具有TComponent类型.所有者主要用于管理设计组件的生命周期.也就是说,您放置在表单设计器(或实际上是其他设计表面)上的组件,其生命周期完全由框架管理. documentation说:
Indicates the component that is responsible for streaming and freeing this component.
创建表单时,流式处理框架会解析.dfm文件并实例化其中列出的组件.通常使用指定为表单的所有者创建这些组件.
在组件生命的另一端是破坏.当一个组件被销毁时,它也会破坏它拥有的所有组件.为了一个具体的例子,考虑一个位于TForm上的TButton,在设计时放置在那里.流式框架创建按钮,将其所有者设置为表单.作为TComponent的后代,该表单维护着它拥有的所有组件的列表.当表单被销毁时,它会遍历所拥有的组件列表并销毁它们.按钮以这种方式被破坏.
这有很多细微差别:
>组件不需要由表单拥有.例如,在运行时创建的组件由传递给构造函数的任何组件拥有.
>组件不需要拥有者,您可以将nil传递给构造函数.在这种情况下,程序员仍然负责销毁组件.
>可以在组件的生命周期内更改所有权.
因为流式框架实例化组件,所以TComponent的构造函数被声明为virtual:
constructor Create(AOwner: TComponent); virtual;
如果从TComponent后代派生,并且希望将派生组件放置在设计图面上,则必须遵守此虚拟构造函数.如果在TComponent后代中定义构造函数,则它必须覆盖此虚构造函数.
值得指出的是,Win32有一个完全不同的窗口所有者概念,不应该与同名的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中,框架设置了窗口所有者,并没有提供简单的机制来覆盖框架的选择.如果确实需要影响窗口所有权,则必须覆盖CreateParams并设置Params.WndParent.遗憾的是,在VCL处理Delphi 7中的所有权时存在许多问题,有时需要在这些有点血腥的细节中进行处理.
为了表明混淆是多么容易,VCL documentation说:
WndParent: The window handle of the parent window. This is the same as the Handle property of the parent control.
这是完全错误的.对于顶级窗口,这是所有者而不是父级.
亲
Parent
是TControl中定义的属性,类型为TWinControl.广义上,此属性用于公开父控件和子控件的Win32概念. 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是在TControl中定义的.现在,TControl没有窗口化,因此在Win32意义上TControl不是子控件,因为Win32窗口的子窗口本身就是窗口.因此,具有已定义父级的TControl是VCL意义上的子级,称为非窗口子控件.这些非窗口控件将自身绘制为其父级绘制处理程序的一部分.这种控制的典型例子是TLabel.
请注意,当窗口控件(即TWinControl后代)被销毁时,它也会销毁其所有子节点.
TWinControl后代可以使用ControlCount和Controls []属性枚举其子项.这些列举了窗口和非窗口的子项.