一般的に言えば、GUIコントロールにデータ(またはあなたの場合はオブジェクト)を保存することはお勧めできないため、あなたの質問はあまり役に立ちません。デザインの変更方法に関する David のコメントも参照してください。
ただし、コンボボックスがフォームの直接の子であることと、フォームの別の子(この場合はフレーム)の子であることの違いは、質問に答えるのが興味深いものです。どうやら、そのフレームのデストラクタが呼び出される前に、コンボ ボックスの項目が破棄されます。探索する明白な代替手段は、overriding Frame.BeforeDestruction
、overriding Frame.DestroyWindowHandle
、overriding Frame.DestroyWnd
、または overriddenWM_DESTROY
での catchFrame.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
プロパティを nil に設定する別の方法も見つけました。OnDestroy
procedure TForm2.FormDestroy(Sender: TObject);
begin
Frame1.Parent := nil;
end;
この場合、フレームのデストラクタ内のコンボ ボックスに格納されているオブジェクトを安全に破棄できます。しかし、この解決策は説明的ではないため、現在の解決策よりもさらに悪いです。その後Frame1.FreeComboObjects
、はるかに優れています。