Ваш вопрос не очень полезен, потому что - вообще говоря - не рекомендуется хранить данные (или объекты в вашем случае) в элементе управления графическим интерфейсом. См. Также комментарий Дэвида о том, как изменить дизайн.
В чем заключается вопрос, в котором возникает вопрос о том, как отвечать на вопрос, является ли разница между полем со списком, являющимся дочерним элементом формы, и быть ребенком другого ребенка формы (в этом случае ваша рамка). По-видимому, элементы со списком уничтожены до того, как вызывается деструктор этого фрейма. Очевидными альтернативами для изучения являются: переопределение Frame.BeforeDestruction
, переопределение Frame.DestroyWindowHandle
, переопределение Frame.DestroyWnd
или перехват WM_DESTROY
в переопределенном Frame.WndProc
, но ни одна из них не вызывается до того, как элементы уже ушли.
Следующее, что нужно попробовать - это повторить это для поля со списком. Оказывается, когда WM_DESTROY
приходит в поле со списком, элементы все еще там. Однако будьте осторожны с тем, чтобы поймать это сообщение, когда управление действительно уничтожается, потому что VCL может часто воссоздавать поле со списком. Реализовать его с помощью вставляя класс для TComboBox
следующим образом:
unit Unit2;
interface
uses
Windows, Messages, Classes, Controls, Forms, StdCtrls;
type
TComboBox = class(StdCtrls.TComboBox)
protected
procedure WndProc(var Message: TMessage); override;
end;
TFrame1 = class(TFrame)
ComboBox1: TComboBox;
end;
implementation
{$R *.dfm}
{ TComboBox }
procedure TComboBox.WndProc(var Message: TMessage);
var
I: Integer;
begin
if (Message.Msg = WM_DESTROY) and (csDestroying in ComponentState) then
for I := 0 to Items.Count - 1 do
Items.Objects[I].Free;
inherited WndProc(Message);
end;
end.
Теперь, чтобы ответить на ваш вопрос: «Является ли это лучше?»
Да, это потому, что оно обеспечивает уверенность в разрушении объекта на уровне кадра. Другими словами: вам не нужно , чтобы иметь дело с этим для каждого экземпляра отдельно.
И нет, это не так, поскольку это решение требует, чтобы объекты в поле со списком были освобождены в любых обстоятельствах, которые ограничивают использование ненужной дополнительной границей.
Итак, этот ответ полезен? Ну, если это мешает вам использовать ваш текущий подход, то это так.
Кроме того, я также нашел другую альтернативу, установив Parent
свойства фрейма к нулю в вмещающей форме OnDestroy
обработчика:
procedure TForm2.FormDestroy(Sender: TObject);
begin
Frame1.Parent := nil;
end;
В этом случае, вы можете безопасно уничтожить объекты, хранящиеся в комбо в пределах деструктора кадра. Но это решение еще хуже, чем ваш текущий, потому что он не описательный. Тогда Frame1.FreeComboObjects
намного лучше.
Мой совет - изменить свой дизайн. Не используйте поле со списком этих объектов. Пусть кадр принадлежит им в любом контейнере, который вам нравится, например. 'TObjectList'. Затем вы можете уничтожить этот контейнер в деструкторе вашего фрейма. –