Whilst browsing the newsgroups this question seems to be asked very often:
How do I create controls at runtime?
as well as
Why can I not see the control I just created?
and
How do I assign event handlers to my controls?
Here I intend to answer all of the above questions and provide sample code to show just how easy it is to do.
procedure TForm1.AddNewButtonClick(Sender: TObject);
var
(* Pointer to the new button that we are going to create *)
NewButton : TButton;
begin
(*
This creates (in memory) the new button with the owner of it
being the form (self) so that the NewButton will be
destroyed automatically when the form is destroyed
*)
NewButton := TButton.create(self);
(*
By using the with statement on the new button we do not need to
to keep referencing its properties with NewButton. all the time
*)
with NewButton do
begin
(*
Set Top so that it appears underneath our two fixed buttons
*)
Top := 30;
(*
Make the width large enough to hold the caption
*)
Width := 60;
(*
This line takes a little more explanation. Every WinControl
has a ControlCount property which holds the number of
controls that are parented by it. So self.ControlCount will
return the number of controls on our form. We know of two of
these controls (our fixed buttons so by taking 2 off this we
have the number of NewButtons that we have created and
multiplying this by the width we have the left position of
the NewButton
*)
Left := Width * (self.ControlCount-2);
(*
This is the line that is most often forgotten, the parent
property should be set to the WinControl the button (or
any other component) is to be displayed on. In our case
this is self which will be the main form, if it is not
set your button will not be displayed
*)
Parent := self;
(*
This assigns the procedure CustomButtonClick (which will be
written later) to the OnClick event of the NewButton
*)
OnClick := CustomButtonClick;
(*
We calculate the button number as early, and add this to
the caption so that all of our new buttons will
have different captions
*)
Caption := 'Button '+ inttostr (self.ControlCount-2);
end; //With
end;
Next we need to complete the procedure for when the 'Delete Last Button' button is clicked
procedure TForm1.DeleteLastButtonClick(Sender: TObject);
begin
(* Make sure there are some new buttons on the form *)
if Self.ControlCount>2 then
(* Delete the last added button *)
TButton (Controls[ControlCount-1]).destroy;
end;
Finally we need to write a new procedure to deal with the OnClick event for all our new buttons. First define it in the private section of the unit:
private
{ Private declarations }
procedure CustomButtonClick(Sender: TObject);
Notice that the procedure has the same layout as the other button clicks, so if we wish to respond to another event just see what the syntax is using one of the Buttons at design time (i.e. double clicking the event in the Object Inspector). Copy it, changing the procedure name to something different. And assign the event to that procedure (e.g. OnDragDrop := MyNewDragDop). Then write the procedure using the required syntax.
procedure TForm1.CustomButtonClick(Sender: TObject); begin (* Display the caption of the pressed button on a Message *) (* Box to indicate which button was pressed *) (* The pressed button is got from the sender parameter of the procedure *) (* which needs casting to TButton *) ShowMessage(TButton(Sender).caption + ' Pressed'); end;