Where to free dynamically allocated TFrame's components' objects?

delphi, destructor, tframe

Solution

You say that when the destructor for the TFrame is called, the Items of the ComboBox have already been cleared. That's not the case, ComboBox items are never cleared. When Items is destroyed by the ComboBox, they've got a count of only 0.

When you exit your application and the VCL destroys the form containing the frame and the ComboBox, the native ComboBox control is also destroyed by the OS since it is placed in a window being destroyed. When you later access the items to be able to free your objects in the frame destructor, the VCL have to recreate a native ComboBox control, having an item count of 0.

The solution I'd propose is easy. Don't leave freeing your frame to the framework, instead, destroy your frame in the `OnDestroy` event of your form. That would be before the underlying window of the form is destroyed, hence you'll be able to access your objects.

form unit

procedure TMyForm.FormDestroy(Sender: TObject);
begin
  MyFrame.Free;
end;

frame unit

destructor TMyFrame.Destroy;
var
  i: Integer;
begin
  for i := 0 to ComboBox1.Items.Count - 1 do
    ComboBox1.Items.Objects[i].Free;
  inherited;
end;

Problem

I have a form containing a `TFrame`. The `TFrame` contains a `ComboBox` that is dynamically populated. Each `ComboBox` entry has an associated object. By the time the overridden destructor for the `TFrame` is called, the Items in the `ComboBox` have already been cleared without freeing their associated objects. This happens whether I drop the `ComboBox` on the form in designer view, or dynamically create it in code with either nil or the `TFrame` as its owner. I currently use the `OnDestroy` event of the containing `TForm` to call a clean-up procedure of the contained `TFrame`. Is there a better way that would not need an explicit procedure call by the `TFrame`'s container? Where ideally should the objects added dynamically to the `ComboBox` be freed?

Original source