Jamo
Jamo

Reputation: 3258

Deleting all components of a certain class on a form (Delphi)

This is probably a stupid question, but my brain is just cooked enough I think I'm going to use one of my "lifelines" to see if I can get some help from my stack overflow friends. ;)

I need to delete all occurrences of a particular component type on my main form (some of them are inside panels or tabsheets, but all on and owned by the same form). Here's what I have now:

for i := 0 to frmMain.ComponentCount - 1 do  
  begin  
    if frmMain.Components[i] is TMyClass then frmMain.Components[i].Destroy;  
  end;    

The problem is (and I knew it would be before I compiled it) that once I destroy the component, the form's component list re-indexes and I end up out of bounds.

What's the best way to solve this? I thought about adding the "found" components to a standalone array, and then walk through that after this loop to delete them, which I think will work.... but is that the best approach?

TIA


UPDATE:

You guys rock. Thanks. : )

Upvotes: 12

Views: 16617

Answers (6)

Mehdi Baghdadi
Mehdi Baghdadi

Reputation: 1

For Fine Contrle in form or panel can use this code

var

 i:Integer;

begin

for i := 0 to Panel1.ControlCount - 1 do

  begin

    if Panel1.Controls[i] is TEdit then
       Tedit(Panel1.Controls[i]).text := '';

  end;

Upvotes: -2

pritaeas
pritaeas

Reputation: 2093

It may not happen in your case, but the if frmMain.Components[i] is TMyClass check will also return true for descendant classes of TMyClass. If you are really looking for the removal of one specific class, you may need to add an extra check of the ClassName.

Upvotes: 2

ArafatZG
ArafatZG

Reputation: 1

If you need to check & destroy a named known component Use

If YourComponent <> Nil Then
  YourComponent.Free;

Upvotes: -3

Vegar
Vegar

Reputation: 12898

The same solution with a while-loop:

i := 0;
while i < frmMain.ComponentCount do
begin
  if frmMain.Components[i] is TMyClass then
    frmMain.Components[i].Free 
  else
    inc(i);
end;

Upvotes: 1

Brian Frost
Brian Frost

Reputation: 13454

You're nearly right. Your loop should look like

for i := frmMain.ComponentCount - 1 downto 0 do
begin
  if frmMain.Components[i] is TMyClass then
    frmMain.Components[i].Free;
end;

This way the call to the function "frmMain.ComponentCount" gets done at the beginning and not again.

You should also call Free as above, not Destroy - I can't remember why at the moment. Bri

Upvotes: 28

jrodenhi
jrodenhi

Reputation: 2237

Start at the top and work backwards.

viz:

for i := frmMain.ComponentCount - 1 downto 0 do
begin
  if frmMain.Components[i] is TMyClass then frmMain.Components[i].Free;
end; 

Call free instead of Destroy. Free calls Destroy after checking for a valid reference.

Upvotes: 10

Related Questions