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.
source to share
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.
source to share
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
.
source to share