Destroy shapes on the form close

Currently when I click the button it will create some shapes in a new shape. Once I close the new shape, how can I destroy the shapes it created.

I can add more information if needed, but hoped there was an easy way to destroy all instances of TMachine when the form is closed.

TMachine

is the TShape class

procedure TFLayout1.GetClick(Sender: TObject);
var
  azone: string;
  adept: string;
  machine : TMachine;
begin
  fdb.count := 0;  //keeps track of number of machines in zone
  azone := MyDataModule.fDB.GetZone(Name);    //gets name of zone
  adept := TButton(Sender).Name;       //gets name of dept
  fdeptlayout.ListBox1.Clear;

  fdeptlayout.show;
  with fdeptlayout.ADOQuery1 do
    begin
         sql.Clear;
         sql.BeginUpdate;
         sql.Add('SELECT');
         sql.Add(' *');
         sql.Add('FROM');
         sql.Add(' `MList`');
         sql.Add('WHERE `Zone` = :myzone ');
         sql.Add(' AND `Dept` = :mydept');
         sql.EndUpdate;

         parameters.ParamByName('myzone').Value := azone;
         parameters.ParamByName('mydept').Value := adept;
         open;
    end;

  //gets number of machines in total
  while not fdeptlayout.ADOQuery1.Eof do
    begin
      fdb.count := fdb.count+1;
      fdeptlayout.ADOQuery1.Next;
    end;

  //restarts back at first query
  fdeptlayout.ADOQuery1.First;

   //clears the last x value
   fdb.LastX :=0;

  //creates the shape
  while not fdeptlayout.ADOQuery1.Eof do
    begin
        machine := MachineShape.TMachine.Create(self);
        machine.Parent := fdeptlayout;
        machine.PlaceShape(44,44,'CM402','first','123/33/123');
        fdeptlayout.ListBox1.Items.Add(fdeptlayout.ADOQuery1.FieldByName('Name').AsString);
        fdeptlayout.ADOQuery1.Next;
    end;
end;

      

TMachine class

unit MachineShape;


interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, extctrls,myDataModule,Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls;

type

TMachine = class(TShape)
  private
    { Private declarations }
  public
    { Public declarations }
    procedure PlaceShape(sizeW,sizeH :integer; name, order,asset : string);
  end;
implementation



    Procedure TMachine.PlaceShape(sizeW,sizeH :integer; name, order,asset : string);
    begin
       self.width :=  sizeW;
       self.height := sizeH;
       self.top := 136;
       self.left := MyDataModule.fDB.LastX +2;//set left
       MyDataModule.fDB.lastx := left + sizeW;
       showmessage(inttostr(mydatamodule.fDB.LastX));
    end;

end.

      

FDeptLayout

unit DeptLayout;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls,mydatamodule, Vcl.Forms, Vcl.Dialogs, Data.DB, Data.Win.ADODB, Vcl.StdCtrls,
  Vcl.ExtCtrls;

type
  TfDeptLayout = class(TForm)
    ADOQuery1: TADOQuery;
    ListBox1: TListBox;
    procedure FormClose(Sender: TObject; var Action: TCloseAction);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  fDeptLayout: TfDeptLayout;

implementation

{$R *.dfm}

procedure TfDeptLayout.FormClose(Sender: TObject; var Action: TCloseAction);
begin

end;

end.

      

+3


source to share


2 answers


The code shown uses the VCL ownership model , and the form will free it up for you, since you just pass the form yourself as the owner of your components when you create it:

machine := MachineShape.TMachine.Create(self);

      

since this is called from the TFLayout1 class, when a particular form instance destroys itself, it will release all of the components it owns.

For more information, you can read the article: Owner vs. Parent in Delphi .



Edit

From the comments, this has resulted in instances being created TMachine

in a class other than the form you are showing it on, and you are not destroying the form instance when you close it, so you can achieve what you want to make the change:

  • Make the shape where the shapes will be shown by the owner by modifying the code to create them for this:

    //don't use self, now the parent is the instance referenced by fdeptlayout
    machine := MachineShape.TMachine.Create(fdeptlayout);
    
          

  • In your Tfdeptlayout class, add an OnClose handler with this code:

    begin
      for I := ComponentCount - 1 downto 0 do
        if Components[I] is TMachine then
          Components[I].Free;
    end;
    
          

However, you really need to read the documentation and article links to get some idea of ​​what's going on behind the scenes in your Delphi application.

+5


source


You assign to Owner

your TMachine

objects. The forms will be automatically released when released Owner

.

Assuming that TFLayout1

is your Form class, then by default it will not be automatically deallocated when closed. The closed form is hidden by default, so you can re-show when needed. To actually release it on close, you need to either set the parameter Action

in the event TForm.OnClose

to caFree

, or call TForm.Free()

directly some time after the form is closed (for example, if you show the form with ShowModal()

, you can call Free()

after exiting ShowModal()

).



If you want to free the shapes yourself without relying on the behavior Owner

, set Owner

to on nil

when you create the shapes and store the pointers TMachine

in TList

that you can scroll when needed to free each shape, or TObjectList

with the property OwnsObjects

set to true so you can Clear()

when needed. For example, in the Form OnClose

.

+3


source







All Articles