Create, destroy and count values inside dynamic controls in Delphi

472 Views Asked by At

I have questions about how to create dynamic controls, how destroy and how get value inside newly created control.

Create and count edits create in form worked correctly, but where I create edits in panels with buttons to destroy chosen panel (Panel [Edit, button]), it's create correctly, but count doesnt work.

And I don't know how to destroy chosen by me panel with edit without error (I didn't make it yet in code below).

I have this code:

unit Unit1;

interface

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

type
  TfrmMain = class(TForm)
    btnCreateNewObject: TButton;
    btnCountValues: TButton;
    btnCreateNewPanels: TButton;
    btnAllEditsInPanels: TButton;
    procedure btnCreateNewObjectClick(Sender: TObject);
    procedure FormCreate(Sender: TObject);
    procedure btnCountValuesClick(Sender: TObject);
    procedure btnCreateNewPanelsClick(Sender: TObject);
    procedure btnAllEditsInPanelsClick(Sender: TObject);
  private
    dynEdit: TEdit;
    dynPanel: TPanel;
    yposition: integer;
    ypositionpanel: integer;
    { Private declarations }
  public
    { Public declarations }
  end;

var
  frmMain: TfrmMain;

implementation

{$R *.dfm}

procedure TfrmMain.btnCountValuesClick(Sender: TObject);
var
  i: integer;
  res: integer;
begin
  res := 0;
  for i := 0 to Self.ControlCount - 1 do
  begin
    if Controls[i] is TEdit then
    begin
      res := res + StrToInt((Controls[i] as TEdit).Text);
    end;
  end;
  ShowMessage(IntToStr(res));
end;

procedure TfrmMain.btnCreateNewObjectClick(Sender: TObject);
begin
  dynEdit := TEdit.Create(Self);
  with dynEdit do
  begin
    Parent := frmMain;
    Width := 80;
    Height := 25;
    Top := yposition;
    Left := 3;
  end;
  yposition := yposition + 26
end;

procedure TfrmMain.btnCreateNewPanelsClick(Sender: TObject);
begin
  dynPanel := TPanel.Create(Self);
  with dynPanel do
  begin
    Parent := frmMain;
    Width := 100;
    Height := 40;
    Top := ypositionpanel;
    Left := 120;
    dynEdit := TEdit.Create(Self);
    with dynEdit do
    begin
      Parent := dynPanel;
      Width := 80;
      Height := 25;
      Top := 3;
      Left := 3;
    end;
  end;
  ypositionpanel := ypositionpanel + 41;
end;

procedure TfrmMain.btnAllEditsInPanelsClick(Sender: TObject);
var
  i, j: integer;
  res: integer;
begin
  res := 0;
  for i := 0 to Self.ControlCount - 1 do
  begin
    for j := 0 to dynPanel.ControlCount - 1 do
    begin
      if dynPanel.Controls[j] is TEdit then
      begin
        res := res + StrToInt( (Controls[j] as TEdit).Text );
      end;
    end;
  end;
  ShowMessage(IntToStr(res));
end;

procedure TfrmMain.FormCreate(Sender: TObject);
begin
  yposition := 1;
  ypositionpanel := 1;
end;

end.
object frmMain: TfrmMain
  Left = 0
  Top = 0
  Caption = 'frmMain'
  ClientHeight = 500
  ClientWidth = 888
  Color = clBtnFace
  Font.Charset = DEFAULT_CHARSET
  Font.Color = clWindowText
  Font.Height = -11
  Font.Name = 'Tahoma'
  Font.Style = []
  OldCreateOrder = False
  OnCreate = FormCreate
  PixelsPerInch = 96
  TextHeight = 13
  object btnCreateNewObject: TButton
    Left = 775
    Top = 475
    Width = 113
    Height = 25
    Caption = 'Create new edit'
    TabOrder = 0
    OnClick = btnCreateNewObjectClick
  end
  object btnCountValues: TButton
    Left = 775
    Top = 444
    Width = 113
    Height = 25
    Caption = 'Count all edits'
    TabOrder = 1
    OnClick = btnCountValuesClick
  end
  object btnCreateNewPanels: TButton
    Left = 648
    Top = 475
    Width = 121
    Height = 25
    Caption = 'Create new panels'
    TabOrder = 2
    OnClick = btnCreateNewPanelsClick
  end
  object btnAllEditsInPanels: TButton
    Left = 648
    Top = 444
    Width = 121
    Height = 25
    Caption = 'Count all edits in panels'
    TabOrder = 3
    OnClick = btnAllEditsInPanelsClick
  end
end
1

There are 1 best solutions below

7
On

You are iterating only through the Edit controls that are direct children of the Form itself, or of the last Panel created. You are not iterating through all of the Panels.

Use a TList or other suitable container to keep track of the Edits you create dynamically, then you can loop through that list/container when needed. And when you are ready to remove a Panel from the Form, simply Remove() its child TEdit from the list and then Free() the Panel, which will free the TEdit for you.

For example:

unit Unit1;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants,
  System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls, Vcl.ExtCtrls,
  System.Generics.Collections;

type
  TfrmMain = class(TForm)
    btnCreateNewObject: TButton;
    btnCountValues: TButton;
    btnCreateNewPanels: TButton;
    btnAllEditsInPanels: TButton;
    procedure btnCreateNewObjectClick(Sender: TObject);
    procedure FormCreate(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
    procedure btnCountValuesClick(Sender: TObject);
    procedure btnCreateNewPanelsClick(Sender: TObject);
    procedure btnAllEditsInPanelsClick(Sender: TObject);
    procedure DestroyPanel(Sender: TObject);
  private
    { Private declarations }
    AllEdits: TList<TEdit>;
    yposition: integer;
    ypositionpanel: integer;
  public
    { Public declarations }
  end;

var
  frmMain: TfrmMain;

implementation

{$R *.dfm}

procedure TfrmMain.btnCountValuesClick(Sender: TObject);
var
  i, res: integer;
  dynEdit: TEdit;
begin
  res := 0;
  for i := 0 to AllEdits.Count - 1 do
  begin
    dynEdit := AllEdits[i];
    if dynEdit.Parent = Self then
      res := res + StrToInt(dynEdit.Text);
  end;
  ShowMessage(IntToStr(res));
end;

procedure TfrmMain.btnCreateNewObjectClick(Sender: TObject);
var
  dynEdit: TEdit;
begin
  dynEdit := TEdit.Create(Self);
  try
    with dynEdit do
    begin
      Parent := Self;
      Width := 80;
      Height := 25;
      Top := yposition;
      Left := 3;
    end;
    AllEdits.Add(dynEdit);
  except
    dynEdit.Free;
    raise;
  end;
  yposition := yposition + 26
end;

procedure TfrmMain.btnCreateNewPanelsClick(Sender: TObject);
var
  dynPanel: TPanel;
  dynEdit: TEdit;
  dynButton: TButton;
begin
  dynPanel := TPanel.Create(Self);
  try
    with dynPanel do
    begin
      Parent := Self;
      Width := 200;
      Height := 40;
      Top := ypositionpanel;
      Left := 120;
    end;
    dynEdit := TEdit.Create(dynPanel);
    with dynEdit do
    begin
      Parent := dynPanel;
      Width := 80;
      Height := 25;
      Top := 3;
      Left := 3;
    end;
    dynButton := TButton.Create(dynPanel);
    with dynButton do
    begin
      Parent := dynPanel;
      Width := 100;
      Height := 25;
      Top := 3;
      Left := 100;
      Caption := 'Destroy this pnl';
      onClick := DestroyPanel;
    end;
    AllEdits.Add(dynEdit);
  except
    dynPanel.Free;
    raise;
  end;
  ypositionpanel := ypositionpanel + 41;
end;

procedure TfrmMain.DestroyPanel(Sender: TObject);
var
  dynPanel: TPanel;
  dynEdit: TEdit;
begin
  dynPanel := TPanel(TButton(Sender).Owner);
  dynEdit := TEdit(dynPanel.Controls[0]);
  AllEdits.Remove(dynEdit);
  dynPanel.Free;
end;

procedure TfrmMain.btnAllEditsInPanelsClick(Sender: TObject);
var
  i, res: integer;
  dynEdit: TEdit;
begin
  res := 0;
  for i := 0 to AllEdits.Count - 1 do
  begin
    dynEdit := AllEdits[i];
    if dynEdit.Parent <> Self then
      res := res + StrToInt(dynEdit.Text);
  end;
  ShowMessage(IntToStr(res));
end;

procedure TfrmMain.FormCreate(Sender: TObject);
begin
  yposition := 1;
  ypositionpanel := 1;
  AllEdits := TList<TEdit>.Create;
end;

procedure TfrmMain.FormDestroy(Sender: TObject);
begin
  AllEdits.Free;
end;

end.