[fpc-pascal] Freeing dynamic controls

Frederic Da Vitoria davitofrg at gmail.com
Tue Dec 17 16:38:31 CET 2013


Hello,

In the following program, I get a runtime error I don't understand. This is
a stripped down version of the code. This was written in Delphi 1, I'll end
up rewriting this in a completely different manner, but for the sake of
understanding, could someone explain to me what is wrong here?

The program dynamically creates and frees controls. To make it simple,
dynamically created ShapeButtons are inserted as children of a dynamically
created Panel, and the code only frees this Panel, hoping that this will
trigger freeing the children controls. IIUC, this hasn't changed since
Delphi 1 and it is still how it is supposed to work. When I put a
breakpoint in line 79, I do see the Panel being freed. Furthermore, if I
debug the program in 1.0.14, the program breaks 12 times on wincontrol.inc
line 5214, this being triggered by the call to RemoveControl on line 78. I
can't make it break on the matching line 5209 in 1.2RC1.

But (and this is my issue) the program triggers a "Duplicate name"
exception on line 60. So although the successful v1.0.14 breakpoint in
wincontrol.inc seems to mean that the controls were freed, the "Duplicate
Name" would mean that this was not true.

Can someone explain what is going on here?

unit Memoire2;

{$MODE Delphi}

interface

  uses
    Sysutils, Forms, ExtCtrls, Controls, StdCtrls, Classes, Buttons;

  type

    TForm1 = class(TForm)
      btn_New: TBitBtn;
      procedure DisplayForm ;
      procedure FormInit (Sender: TObject);
      procedure btn_NewClick(Sender: TObject);
    private
      { Private declarations }
    public
      { Public declarations }
    end;

    TShapeButton = class(TButton)
    private
      { Private declarations }
    public
      { Public declarations }
      Col, Lin : integer ;
    end;

  var
    b_Columns : byte ;
    b_Lines : byte ;
    Col1, Lin1, Col2, Lin2 : integer ;
    Form1: TForm1;
    tp_Panel : TPanel ;

  const
    FORM_MARGIN = 10 ;
    MAIN_FRAME_TAG = 999 ;

implementation

  {$R *.lfm}

  procedure TForm1.DisplayForm ;
  var
    wh, ww : integer ;
    procedure SetButton (pc, pl : byte) ;
    var
      newbutton : TShapeButton ;
      wt, wl : integer ;
    begin
      newbutton := TShapeButton.Create (Self) ;
      wt := (pl-1) * (tp_Panel.Height-1) div b_Lines ;
      wl := (pc-1) * (tp_Panel.Width-1) div b_Columns ;
      with newbutton do begin
        name := 'sb'+inttostr(pc)+'_'+inttostr(pl) ;
        caption := '' ;
        SetBounds (wl, wt, wh, ww) ;
      end {with} ;
      newbutton.col := pc ;
      newbutton.lin := pl ;
      newbutton.Parent := tp_Panel
//      tp_Panel.InsertControl (newbutton) { old code, does not work any
better }
    end ;
  var
    c1, l1 : byte ;
    wc : TControl ;
  begin
    c1 := 0 ;
    while c1 < (ControlCount) do begin
      if Controls [c1] .Tag = MAIN_FRAME_TAG
        then begin
          wc := Controls [c1] ;
          RemoveControl (wc) ;
          wc.Free
        end {then}
        else Inc (c1)
    end {while} ;
    wh := (Form1.ClientHeight - 2*FORM_MARGIN) div b_Lines ;
    ww := (btn_New.Left - 2*FORM_MARGIN) div b_Columns ;
    if wh < ww { rend les cases carrées }
      then ww := wh
      else wh := ww ;
    tp_Panel := TPanel.Create (Self) ;
    tp_Panel.ParentColor := TRUE ;
    tp_Panel.Tag := MAIN_FRAME_TAG ; { tags the control for deletion }
    with tp_Panel do begin
      SetBounds (FORM_MARGIN, FORM_MARGIN, ww*b_Columns, wh*b_Lines) ;
      BevelOuter := bvNone
    end {with} ;
    wh := (tp_Panel.Height-1) div b_Lines - 3 ;
    ww := (tp_Panel.Width-1) div b_Columns - 3 ;
    if wh < ww
      then ww := wh
      else wh := ww ;
    for c1 := 1 to b_Columns do
      for l1 := 1 to b_Lines do
        SetButton (c1, l1) ;
    InsertControl (tp_Panel) ;
    btn_New.Enabled := TRUE
  end;

  procedure TForm1.FormInit (Sender: TObject);
  begin
    DisplayForm ;
  end;

  procedure TForm1.btn_NewClick(Sender: TObject);
  begin
    DisplayForm ;
  end;

begin
  b_Lines := 3 ;
  b_Columns := 4 ;
end.

-- 
Frederic Da Vitoria
(davitof)

Membre de l'April - « promouvoir et défendre le logiciel libre » -
http://www.april.org
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.freepascal.org/pipermail/fpc-pascal/attachments/20131217/c482c007/attachment.html>


More information about the fpc-pascal mailing list