Title: Creating Arrays of Objects at Design time
Question: In Visual Basic you can create Arrays of objects at design time, how is this done in Delphi?
Answer:
Why use an Array?
When you need to perform the same action on a lot of controls it is quicker to code, and easier to read and maintain if you can loop through all the controls and perform your desired action on them. An example of doing it with out an array would be:
Button1.hide;
Button2.hide;
Button3.hide;
Button4.hide;
Button5.hide;
Button6.hide;
.............
Whilst if these were stored in an array you would just need:
for iTemp := 1 to 10 do
ButtonArray[iTemp].visible := True;
A case where this maybe useful is if you have an entry form with a lot of checkboxes, and you wish to give the user a reset button which would uncheck all the boxes. You could just loop through all the components on the form looking for checkboxes, but if some did not need to respond to the reset then this may not be feasible.
Getting Started
What we need to do first is declare our array in the unit that contains the form with the controls that we wish to reference. In the example I am using TButtons so the declaration is done like this:
ButtonArray : array [1..10] of TButton;
A point to note here is that just because we have created an Array of TButton, the buttons themselves have not been created, just pointers to them.
Next we need to place the required controls (TButtonts) on the Form. In this example I placed ten Buttons on the form and kept with the default names as this made them easier to search for and add to the array later.
Finally in this section we need to make our array of buttons point to those that we placed on the form. This is do in the FormCreate event by:
procedure TForm1.FormCreate(Sender: TObject);
var iTemp1 : Integer;
iTemp2 : Integer;
begin
{ Loop through all the buttons to add to the array }
for iTemp1 := 1 to 10 do
begin
{ Loop through all controls on the form looking for
the buttons we wish to add }
for iTemp2 := 0 to ComponentCount-1 do
begin
if (Components[iTemp2].Name =
'Button'+inttostr(iTemp1)) then
begin
{ It must be a button so can cast it safely }
ButtonArray[iTemp1] := TButton(Components[iTemp2]);
end;
end; // for all components
end; // for all buttons
end;
All this procedure does is for each element in the array, look for the component with the required name (e.g. Button6) and then make that element in the array point to that button. If you have used more meaningful button names then you would need to fill the array by:
ButtonArray[1] := NewButton;
ButtonArray[2] := SaveButton;
ButtonArray[3] := LoadButton;
.... etc.Using the Array
Now that we have all the buttons referenced in the array all we need to do to access all of them is to loop through them. In this example I added two two more buttons to the form, one called ShowAll and the other HideAll. And assigned the onClick event of both of buttons to these respective examples:
procedure TForm1.HideAllClick(Sender: TObject);
var
iTemp : Integer;
begin
{ Loop through all the buttons and hide them }
for iTemp := 1 to 10 do
ButtonArray[iTemp].visible := False;
end;
procedure TForm1.ShowAllClick(Sender: TObject);
var
iTemp : Integer;
begin
{ Loop through all the buttons and show them }
for iTemp := 1 to 10 do
ButtonArray[iTemp].visible := True;
end;
As can be seen from the code when the ShowAll button is clicked all the buttons in the array have there visible property set to true. whilst the HideAll does the opposite. This is a very simple example but I hope it shows how much easier it is to do it this way.
Cleaning Up
As all the buttons were created at design time using the IDE and Object Inspector they will be destroyed by their owner (the form) when that is destroyed. Therefore we do not to destroy them as the array only points at them. So there is no cleaning up to be done.