Владелец
Owner
- это свойство, введенное в TComponent
, а сам Owner
имеет тип TComponent
. Owner
используется в основном для управления сроком службы разработанных компонентов. То есть компоненты, которые вы размещаете в конструкторе форм (или на других поверхностях дизайна), и срок службы которых полностью управляется платформой. В документации говорится:
Указывает компонент, который отвечает за потоковую передачу и освобождение этого компонента.
При создании формы структура потоковой передачи анализирует файл .dfm и создает экземпляры компонентов, перечисленных в нем. Эти компоненты обычно создаются с Owner
, указанным в качестве формы.
На другом конце срока службы компонента разрушение. Когда компонент уничтожается, он также уничтожает все компоненты, которыми он владеет. Рассмотрим для конкретного примера TButton
, который находится на TForm
, помещенном туда во время разработки. Платформа потоковой передачи создает кнопку, устанавливая ее Owner
в качестве формы. Форма, являющаяся потомком TComponent
, поддерживает список всех компонентов, которыми она владеет. Когда форма уничтожается, она просматривает список принадлежащих ей компонентов и уничтожает их. Кнопка разрушается таким образом.
К этому есть много нюансов:
- Компоненты не обязательно должны принадлежать форме. Например, компоненты, созданные во время выполнения, принадлежат любому компоненту, который вы передаете конструктору.
- Компоненты не обязательно должны иметь владельца, вы можете передать
nil
конструктору. В этом случае ответственность за уничтожение компонента остается за программистом.
- Право собственности может быть изменено в течение срока службы компонента.
Поскольку структура потоковой передачи создает экземпляры компонентов, конструктор TComponent
объявляется виртуальным:
constructor Create(AOwner: TComponent); virtual;
Если вы производный от потомка 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
не является оконным, поэтому TControl
не является дочерним элементом управления в смысле Win32, потому что дочерние элементы окна Win32 сами являются окнами. Итак, TControl
с определенным Parent
является дочерним элементом в смысле VCL, известным как дочерний элемент управления без окон. Эти элементы управления без окон рисуют себя как часть обработчиков рисования своих родителей. Канонический пример такого элемента управления - TLabel
.
Обратите внимание, что когда оконный элемент управления, являющийся TWinControl
потомком, уничтожается, он также уничтожает всех своих дочерних элементов.
Потомок TWinControl
может перечислять своих потомков, используя свойства ControlCount
и Controls[]
. Они перечисляют дочерние элементы как с окнами, так и без них.
27.08.2015