There is a more general and (in my opinion) more elegant way of tracking the removal of nested controls. Everything else - it allows you to keep up to date the internal list not only when the object is released, but also when its parent changes (for example, if the nested panel moves to another TShiftingPanel ):
type TShiftingPanel = class(TPanel) private FPanels: TList; procedure CMControlChange(var Message: TMessage); message CM_CONTROLCHANGE; end; procedure TShiftingPanel.CMControlChange(var Message: TMessage); begin // обрабатываем сообщение о том, что нам "внутрь" пытаются добавить // или удалить компонент // через установку свойства Parent. // это же сообщение отправляется при удалении вложенного компонента // т.к. при его уничтожении выставляется Parent = nil. if TObject(message.WParam) is TPanelEx then if Boolean(message.LParam) then begin // контрол добавляется FPanels.Add(Pointer(message.WParam)); end else begin // контрол удаляется FPanels.Remove(Pointer(message.LParam)); end; inherited; end;
Thus, there is no need for external tracking of the relevance of the FPanels list - TShiftingPanel itself will monitor this. And the nested panels will only have to set the Parent property.
In addition, I propose to get rid of the property TPanelEx.ShiftingPanel . Rather, do not get rid of, and leave only getter. If I understand correctly, then ShiftingPanel should return the panel on which PanelEx lies. And this is already known from the Parent property:
TPanelEx = class(TPanel) public property ShiftingPanel: TShiftingPanel read GetShiftingPanel; end; function TPanelEx.GetShiftingPanel: TShiftingPanel; begin if Parent is TShiftingPanel then Result:=TShiftingPanel(Parent) else Result:=nil; end;
TShiftingPanelinstalled inTPanelExas a private field? - kami