Delphine
Delphine

Reputation: 49

Control over Delphi form components destroy order

Is there any way to control the order of which a Delphi form is destroying its components?

I got AVs when the form is destroying because it is destroying a component before the other component which accesses the first component.

Currently, I have no way to avoid AVs except free the first component in finalization section

Upvotes: 1

Views: 862

Answers (2)

Delphine
Delphine

Reputation: 49

I did some search and some tests and found how to control the Delphi form components destroy order.

There are two ways, at design time and at runtime:

  1. At design time, Edit the form's DFM, move the first component's object block as first block before any other object blocks of any other components that must be freed after the first one.

  2. At runtime, in form OnCreate, Change ComponentIndex property of first component to any value lower than the other components which depend on it, Say 0, this will make it last one to be freed.

Example: FirstComp.ComponentIndex := 0;

That's it!

As you can see, Delphi frees components in the opposite order of which they were added to the form (LIFO), But we can alter this order as I explained.

Thanks everyone for your valuable help. Appreciate it.

Upvotes: -1

Rudy Velthuis
Rudy Velthuis

Reputation: 28826

You will have to call FreeNotification() on the control being referenced and override the protected Notfication() method of your control that is referencing it.

Say you have a property that links to another component (say, a TEdit):

property EditControl: TEdit read FEdit write SetEdit;

Then, if your property is set to link to such a component, you tell it that you want to be notified when it is freed, by calling its FreeNotification() method:

procedure TMyControl.SetEdit(Value: TEdit);
begin
  if FEdit <> Value then
  begin
    if FEdit <> nil then
      FEdit.RemoveFreeNotification(Self); 
    FEdit := Value;
    if FEdit <> nil then
      FEdit.FreeNotification(Self); 
  end;
end;

This means that your Notification() procedure will be called when the TEdit is destroyed. You will have to override it:

protected
  procedure Notification(AComponent: TComponent; Operation: TOperation); override;
...

procedure TMyControl.Notification(AComponent: TComponent; Operation: TOperation);
begin
  inherited Notification(AComponent, Operation);
  if (Operation = opRemove) and (AComponent = FEdit) then
    FEdit := nil;
end;

That way, you will know when you can access the TEdit component, and when not to anymore. If FEdit is nil, you should not access it.

Examples taken from: http://mc-computing.com/Languages/Delphi/ComponentNotification.html

Documentation: http://docwiki.embarcadero.com/Libraries/Seattle/en/System.Classes.TComponent.FreeNotification

Upvotes: 7

Related Questions