Referencing form objects from procedures

Al p12406  --  March 02, 2005

I added a TCheckListBox to a form. When I moved the code for manipulating it from an event handler (TForm1.Button1Click) to a different procedure it all stopped working and I got an 'undeclared identifier' error on compiling.

After a bit of puzzling I worked out that I needed to have 'Tform1.' in my procedure name (e.g. Tform1.AddToList) and also declare my procedure in the 'type' list for the unit. I think this is because I have to state where an object is found before it can be referenced.

Is that the correct explanation? Am I making my procedure a method of the form?

See what happens when you provide inspirational tutorials! ;)

Thanks,
Al

Guido, DelphiLand Team  --  March 04, 2005

Let's have a look at the following code:

procedure AddToList;
begin
  CheckListBox1.Items.Add('ABC');
end;

procedure TForm1.Button1Click(Sender: TObject); begin AddToList; end;

As you noted, this gives you an error message that says that CheckListBox1 is "not declared".
But... there is a CheckListBox1 in the Interface section of the unit ?! :

type
  TForm1 = class(TForm)
    CheckListBox1: TCheckListBox;

These lines result in the creation of Form1.CheckListBox1 at the moment that Form1 is created. Important: this object is NOT simply called CheckListBox1 but it is Form1.CheckListBox1 ! You can check this by modifying the code in procedure AddToList:

  Form1.CheckListBox1.Items.Add('ABC');

So, why then does the following work?

procedure TForm1.Button1Click(Sender: TObject);
begin
  CheckListBox1.Items.Add(ItemNew);
end;

That's because this is equivalent to:

procedure TForm1.Button1Click(Sender: TObject);
begin
  self.CheckListBox1.Items.Add(ItemNew);
end;

In the code above, Button1Click is a method of TForm1. In a method, "self" refers to the object, Form1 in our case.

And to make things confusing ;) Delphi allows us to omit the word "self". In the code of a method, if you specify nothing in front of an identifier (for example identifier ABC), Delphi assumes that you mean self.ABC. If it doesn't find ABC in the type declaration, then it will look for a variable simply called ABC. If it also doesn't find ABC, then it gives an error message.

Also the following will work, because in the following source code we've made AddToList a method of TForm1. Don't forget to also add AddToList to the "private" or "public" part of the type declaration in the Interface section.

procedure TForm1.AddToList;
begin
  CheckListBox1.Items.Add('ABC');
end;

Al  --  March 07, 2005

Many thanks for the clear explanation - it seems so obvious now.