2

I've registered as component a TFrame's descendant class and I've noticed that the Loaded procedure is executed twice:

Runtime:

  TMyFrame = class(TFrame)
  private
  protected
    procedure Loaded(); override;
  public
    constructor Create(AOwner : TComponent); override;
  end;

constructor TMyFrame.Create(AOwner : TComponent);
begin
  ShowMessage('Before TMyFrame.Create');
  inherited Create(AOwner);
  ShowMessage('After TMyFrame.Create');
end;

procedure TMyFrame.Loaded();
begin
  ShowMessage('Before TMyFrame.Loaded');
  inherited;
  ShowMessage('After TMyFrame.Loaded');
end;

Designtime:

procedure Register;
begin
  RegisterComponents('Test', [TMyFrame]);
end;

Output:

At runtime, on creating a form in which there is a TMyFrame component.

Before TMyFrame.Create

Before TMyFrame.Loaded

After TMyFrame.Loaded

After TMyFrame.Create

Before TMyFrame.Loaded

After TMyFrame.Loaded

At designtime, on adding a TMyFrame to a form:

Before TMyFrame.Create

Before TMyFrame.Loaded

After TMyFrame.Loaded

After TMyFrame.Create

At designtime, opening a form in which there is a TMyFrame component:

Before TMyFrame.Create

Before TMyFrame.Loaded

After TMyFrame.Loaded

After TMyFrame.Create

Before TMyFrame.Loaded

After TMyFrame.Loaded

Why the Loaded procedure is executed twice? How to avoid this?

Fabrizio
  • 7,603
  • 6
  • 44
  • 104
  • If you compile with Debug DCUs you can set a breakpoint and see the callstack. – Uwe Raabe Jun 13 '17 at 08:43
  • *When* do you see these messages? In the IDE? or at Run Time? If in the IDE you don't really care so surround your messages with a test for componentstate = csDesigning. – Dsm Jun 13 '17 at 09:13
  • @Dsm: "After adding a TMyFrame to a form, at runtime,". – Rudy Velthuis Jun 13 '17 at 09:14
  • @Rudy - Thanks -yes I shouldn't speed-read! – Dsm Jun 13 '17 at 09:19
  • @Dsm: It also happens on designtime, I have updated the question by reporting all the output messages. – Fabrizio Jun 13 '17 at 09:30
  • Could maybe check ComponentState for csLoading to see if it has finished such. If you're interested in construction instead of loading could maybe override AfterConstruction method (do call inherited there though) – George Birbilis Oct 18 '21 at 08:04

1 Answers1

7

This behavior is as-designed.

Loaded

Loaded may be called multiple times on inherited forms. It is called every time a level of inheritance is streamed in. Do not allocate memory in an overridden Loaded method without first checking that the memory has not been allocated in a previous call.

Dalija Prasnikar
  • 27,212
  • 44
  • 82
  • 159
  • Do you know a way to distinguish the last execution? (In paritcular, I would like to use some variables that are initialized in the constructor) – Fabrizio Jun 14 '17 at 08:08
  • 1
    No. Probably the safest thing would be moving your code from `Loaded` to `AfterConstruction`. – Dalija Prasnikar Jun 14 '17 at 08:17