Delete Component

I have a panel on which i have placed several components.  What i want to do is go through the panel and (1) Free the component and (2) set it to nil.  At the moment i am using the following code but it does not allow me to set the component to nil:

var
  i:integer;
begin
for i := Panel1.ControlCount - 1 downto 0 do
             With Panel1.Controls[I] do
                   begin
                        Free;
                   end;
end;

The above code works and will delete/free the component but will not set each component to nil

Any ideas?
mi6agentAsked:
Who is Participating?
 
geobulConnect With a Mentor Commented:
I see. Try this (Edit1 is on Panel1):

procedure DeleteComponent(AControl: TControl);
var c: TComponent;
begin
  if Assigned(AControl) then begin
    AControl.Parent := nil;
    c := AControl.Owner;
    if Assigned(c) then c.RemoveComponent(AControl);
    AControl.Free;
  end;
end;

procedure TForm1.Button3Click(Sender: TObject);
var
  i:integer;
begin
  for i := Panel1.ControlCount - 1 downto 0 do
    with Panel1.Controls[I] do
      DeleteComponent(TControl(Owner.FindComponent(Panel1.Controls[I].Name)));

  // for testing only
  if Assigned(Edit1) then ShowMessage('Assigned')
  else ShowMessage('nil');
end;

Regards, Geo
0
 
kretzschmarCommented:
use

for i := Panel1.ControlCount - 1 downto 0 do
  FreeAndNil(Panel1.Controls[I]);

meikl ;-)
0
 
kretzschmarCommented:
anyway, this will not nil any reference-variable you may have anywhere
0
Free Tool: IP Lookup

Get more info about an IP address or domain name, such as organization, abuse contacts and geolocation.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

 
Wim ten BrinkSelf-employed developerCommented:
Once you start freeing components this way, the variables that are pointing to these components are still unaware of their state. If you want to free them and assign nil to them, there's only one way:

begin
  Label1.Free;
  Label1 := nil
  Edit1.Free;
  Edit1 := nil;
  ...etc.

Why? Because the object itself doesn't know which variables are referencing it. There could be just one variable or there might even be thousands of variables all pointing to the same control. Only the developer knows which variables are pointing at the objects thus you have no option but to free them one by one.
0
 
geobulCommented:
Hi,

What actually do you want to set to nil?

var
  i:integer;
begin
for i := Panel1.ControlCount - 1 downto 0 do
              With Panel1.Controls[I] do
                   begin
                        Free;
                   end;
ShowMessage(IntToStr(Panel1.ControlCount)); // will report 0 controls
end;

Regards, Geo
0
 
geobulCommented:
meikl, your code won't work because FreeAndNil expects a variable only. Panel1.Controls[I] is not a variable.

If we are talking about variables referencing these controls then Alex is absolutely correct.
0
 
mi6agentAuthor Commented:
meikl - sorry, should have mentioned i use Delphi 4 Pro which does not have FreeAndNil

Workshop_Alex / meikl - good point.  Any quick way around this or is it just plain old "set each one to nil one by one"
0
 
mi6agentAuthor Commented:
> What actually do you want to set to nil?

All of the components that were on the panel - ie: free and nil them so if i then use something like If assigned(label1) it will show that label1 is not in a "created" state.
0
 
kretzschmarCommented:
>meikl, your code won't work because FreeAndNil expects a variable only.
missed this geo, thanks ;-)
0
 
kretzschmarConnect With a Mentor Commented:
>If assigned(label1) it will show that label1 is not in a "created" state

well, if you do not want the advice from alex,
then you could instead of assigned following

if assigned(findcomponent('label1')) then
  //label1 already exist
else
  //label1 must be created

usual findcomponent searches for the componentname,
so if you create a new one, you should name it as well
(if you drop compnents at designtime the name of the component
and the name of the reference-variable are the same)

this is just a workaround

meikl ;-)
0
 
Wim ten BrinkConnect With a Mentor Self-employed developerCommented:
Well, if you want to set all variables to nil then there is one way, but it's a bit rediculous to do. What you should do in such a case is create an array of pointers to objects. For every variable you want to set to nil, add a pointer to this array pointing to the address of this variable. Fill this array during runtime on your FormCreate method or perhaps even earlier. Then, whenever you want to free and set all those variables to nil, just walk through this list. :-)

Example:

type
  PObject = ^TObject;
  TVarList: array of PObject;
  TForm1 = class(TForm)
    Label1: TLabel;
    Edit1: TEdit;
    procedure FormCreate(Sender: TObject);
  private
    VarList: TVarList;
    procedure Clear;
  end;

procedure TForm1.FormCreate(Sender: TObject);
begin
  SetLength(VarList, 2); // 2 variables...
  VarList[0]^ := @Label1;
  VarList[1]^ := @Edit1;
end;

procedure TForm1.Clear;
var
  I: Integer;
begin
  for I := Low(VarList) to High(VarList) do begin
    VarList[I]^.Free;
    VarList[I]^ := nil;
  end;
end;

Not tested, though so it's probably flawed. But it's just to show what kind of weird code you would have to start to write compared to:

procedure TForm1.Clear;
begin
  FreeAndNil(Label1);
  NreeAndNil(Edit1);
end;

Now, it is up to you. Personally I would hate to have to keep track of addresses of variables so I can access those variables while it is perfectly clear to me where those variables are. My example is just plain ugly. So ugly that I won't insult my compiler by testing it. :-P
0
 
mi6agentAuthor Commented:
Thanks all - some very good points you all have given.  Workshop_Alex - ouch! i see your point on the ugly way to do it.

I have raised the points so i can give you the original 125 points each with a grade A.

Again, thanks to all of you for the input and help.
0
 
geobulCommented:
That's very generous of you. Thanks.
0
 
Wim ten BrinkSelf-employed developerCommented:
Very generous indeed. :-) Thanks.
0
 
kretzschmarCommented:
shall i say similar?

thanks, glad that we helped you

meikl ;-)
0
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

All Courses

From novice to tech pro — start learning today.