Main
Contents
Whats New?
Articles & Tutorials
Hints and Tips
Links
Feedback
About



Inform when updated


Search this site!
 
     powered by FreeFind
Articles::Creating Controls at Run Time


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.

Getting Started - What the program will do
   What we will do is write a very simple program which will comprise of a form with 2 buttons (TButton) on it. One will allow us to add new buttons to the form and the other will delete the last added button. All new buttons that are added will be placed next to each other on the form. When ever one of the new buttons is clicked a dialog box will be displayed showing which button was pressed.


Designing the form in the IDE
   First we need to start a new applictaion, (I called mine RunTime.dpr with the only other unit being main.pas). As it is a very simple program that we are writing all we need to add to the form is 2 buttons, so by selecting the Button from the Standard page of the component palette add 2 new buttons to your form. Place the 2 buttons next to each other at the top of the form calling one AddNewButton and the other DeleteLastButton. Then by using the Object Inspector create the function stubs for the OnClick event of the two buttons. We now have the skeleton of our program but do not run it yet as Delphi will remove our OnClick program stubs as they are not doing anything.
 

Writing the actual code
   All we need to do now is fill in the two procedures (Delphi created for us) for the OnClick events of our two buttons, and write another procedure that will be called when one of our buttons is clicked.

The first procedure to write then is the one for adding the NewButton

     procedure TForm1.AddNewButtonClick(Sender: TObject);
     var
       (* This is a 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 *)
       (* self so that the NewButton will be destroyed automatically when the *)
       (* form is destroyed *)

       NewButton := TButton.create(self);

       (* By using the with statment 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 propery 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 takeing 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 diplayed *)
         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 procudure using the required syntax.

   Here is the procedure for our OnClick event:

     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;


Conclusion
   I hope this has been a useful starter tutorial for creating controls at run time. When writing your own application you may find it is better to store pointers to them in an array or TList so that it is easier to access them. I used the ControlCount on the form as this was the simplist way in the circumstances, but if you have other controls on the form this will probably not be the case. I will be writing a sample application in the future that allows the user to create buttons at runtime assigning them to execuatables on their machine which will be launched when the button is clicked. A custom toolbar and launch pad (like that seen in Microsoft Office).


[Welcome] [Contents ] [Whats New?] [Articles & Tutorials][Hints & Tips] [Feedback] [Links]

Copyright 1997 Allan Carlton. Delphi is a registered trademark of Inprise Corporation. Inprise Corporation in no way endorses or is affiliated with Delphi Central. All other trademarks are the sole property of their respective owners.