delphidelphi-10.4-sydney

Error in IDE on loading custom component. Delphi bug or my mistake?


I found a strange issue with a custom component that creates/destroys subcomponents dynamically.

type
  TPanelTest = class(TPanel)
  private
    FShowPanel : Boolean;
    FPanel : TPanel;
    function GetShowPanel: Boolean;
    procedure SetShowPanel(const Value: Boolean);
    procedure CreateSubPanel;
    procedure DestroySubPanel;
  protected
  public
    constructor Create(AOwner: TComponent); override;
    destructor Destroy; override;
  published
    property ShowPanel : Boolean read GetShowPanel write SetShowPanel;
  end;

...

{ TPanelTest }
constructor TPanelTest.Create(AOwner: TComponent);
begin
  inherited Create(AOwner);
  SetBounds(0, 0, 300, 300);
  ShowPanel := True;
end;

procedure TPanelTest.CreateSubPanel;
begin
  if not Assigned(FPanel) then
  begin
    FPanel := TPanel.Create(Self);
    with FPanel do
    begin
      SetSubComponent(True);
      Parent := Self;
      Caption := '';
      Top := 0;
      Left := 0;
      Height := 50;
      Align := alTop;
    end;
  end;
end;

procedure TPanelTest.DestroySubPanel;
begin
  if Assigned(FPanel) then
    FreeAndNil(FPanel);
end;

function TPanelTest.GetShowPanel: Boolean;
begin
  Result := FShowPanel;
end;

procedure TPanelTest.SetShowPanel(const Value: Boolean);
begin
  FShowPanel := Value;
  if Value then
    CreateSubPanel
  else
    DestroySubPanel;
end;

In run-time and design-time, everything (creating and destroying FPanel) works correct, but if I set ShowPanel to False, then save the project, close and open it again, I get an error:

Error creating form: Access violation at address 50CF4B9C in module 'vcl270.bpl'. Read of address 00000000.

If I manually change ShowPanel to True in the .dfm file, everything starts work correct again.

So, what am I missing? I'm using Delphi 10.4.2 CE

For now, I use a workaround with making SubPanel invisible instead of destroying it, but I want to make this right.


Solution

  • Problem was in SetSubComponent(True):

    ...Unlike top-level components, subcomponents are not saved with the form or data module in which they reside. Instead, a subcomponent appears as the value of a published property of its Owner, and its published properties and events are saved in the form file with the owning component.

    In this case, I don't need to set FPanel as a SubComponent of TPanelTest.