在形式上摧毁形状

Gle*_*rse 3 delphi delphi-xe2

目前,当我点击一个按钮时,它将在新表格上创建一些形状.一旦我关闭新表格,我怎么能破坏它所形成的形状.

如果需要,我可以添加更多信息,但希望有一种简单的方法可以在表单关闭时销毁所有TMachine实例.

TMachine 是一个TShape类

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;
Run Code Online (Sandbox Code Playgroud)

TMachine类

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.
Run Code Online (Sandbox Code Playgroud)

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.
Run Code Online (Sandbox Code Playgroud)

jac*_*ate 5

显示的代码正在利用VCL所有权模型,表单将为您释放它,因为您在创建时只需将表单本身作为组件的所有者传递:

machine := MachineShape.TMachine.Create(self);
Run Code Online (Sandbox Code Playgroud)

因为这是从TFLayout1类调用的,当表单的特定实例正在破坏它时,它将释放所有拥有的组件.

有关更多信息,您可以阅读文章:Delphi中的Owner vs. Parent.

编辑

从注释中,它导致您TMachine在与您显示它的表单不同的类上创建实例,并且在关闭它时不会销毁表单实例,因此,您可以达到您想要进行此更改的内容:

  • 将形状显示为所有者的表单,更改代码以将其创建为:

    //don't use self, now the parent is the instance referenced by fdeptlayout
    machine := MachineShape.TMachine.Create(fdeptlayout);
    
    Run Code Online (Sandbox Code Playgroud)
  • 在您的Tfdeptlayout类上,使用以下代码添加OnClose处理程序:

    begin
      for I := ComponentCount - 1 downto 0 do
        if Components[I] is TMachine then
          Components[I].Free;
    end;
    
    Run Code Online (Sandbox Code Playgroud)

也就是说,您必须阅读文档和参考文章,以便了解Delphi应用程序中幕后发生的事情.