- - * - WhiteUnicorn - * - -




* #WhiteUnicorn/ StartPage/ Documentation/DelphiFAQ >


2938:Creating Dynamic Components at Runtime

KEYWORDS: run-time creation AREA: General

Using Delphi forms and components is simple.  When coupled with the
object inspector, controlling those objects requires little effort.
Creating these types dynamically is also not difficult.  This document
is intended to give you some tips and hints on how to make dynamic
component work for you.

(please note this term "dynamically" is subjective, behind the scenes,
Delphi creates all objects dynamically.  The information presented herein
is for the programmer setting creation/properties/deletion the given
type at run time)

All types (a form or a component) can be created dynamically. To do
this, one needs to put a declaration in the VAR section of their code.
This does not create an instance of the object, it creates a pointer.
This pointer resides in the data segment (if the variable is declared
globally) or the stack (if the variable is declared local to a procedure
or function).  In order to instantiate this class, you must call the
constructor.  This will allocate memory in the computers global heap
for the class instance.  Trying to access the component before
allocating memory will produce a general protection fault.

The Create() constructor is a class method descended from the TObject
Class.  Create() returns a pointer.  This method may or may not take one
or more parameters.  For most components (all objects which descend from
TComponent are referred to as components), the constructor takes one
parameter, the "owner" of type TComponent.

When dynamically creating a component, setting the Owner to "Self"
is the most common practice.  If you are in one of a form's methods,
"Self" refers to that form in that context.  If the owner is a valid
object, freeing that object will also free the "owned" component.
Another common parameter is "Application".  This might be used for a
visual component that will not be displayed to the program's users.
However, most components do not require that you set a specific owner,
so it is not uncommon to set the owner to Nil.  Keep in mind, though,
that you will not be able to change the owner afterwards.  If you do
pass Nil to a component's constructor, you must remember to call that
component's Free method when you are through using the component.

After creation, but before they can be displayed, windowed components
(those descending from TWinControl) require the Parent property to be set.
At the time you set the Parent property, it's usually also a good time to
set other properties of this components instance, including event
handlers (ie, Width, Color, OnClick).

Event handlers are identical to those specified in the object inspector.
Simply set the component's property name for the event you want to handle
to name of the event handler method  you want invoked.  Example 1 below
would call the method called "myclick" whenever the button is clicked.
Please note this method will be sent the appropriate parameters, and its
incoming parameter list must be exact.

Example 1:
var
  b1 : TButton;
begin
  .
  .
  .
  b1 := TButton.Create(Self);
  with b1 do begin
    Left := 20;
    Top := 20;
    Width := 90;
    Height := 50;
    Caption :=  my button';
    Parent := Form1;
    OnClick :=  MyClick;  { a procedure I defined somewhere else }
  end;
  .
  .
  .
end;

The next example demonstrates how to create a button at run time by
clicking a predefined button.  Note the different way the button has
been created.  Either way would work.   Also note the buttons that are
created are not freed in this code, they will be freed when the form
is released.

unit Unit1;
interface

uses
  SysUtils, WinTypes, WinProcs, Messages, Classes, Graphics, Controls,
  Forms, Dialogs, StdCtrls;

type
  TForm1 = class(TForm)
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  procedure myClick(Sender: TObject);
  end;

var
  Form1: TForm1;

const
  i : integer = 0;

implementation
{$R *.DFM}

procedure TForm1.myClick(Sender: TObject);
begin
  with Sender as TButton do
    Self.Caption := ClassName + ' ' + Name;
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  with TButton.Create(self) do begin
    Left := 20;
    Top := 30 + i;
    Width := 120;
    Height := 40;
    Name := 'ThisButton' + IntToStr(i);
    Caption := 'There' + IntToStr(i);
    OnClick :=  MyClick;  { a procedure I defined somewhere else }
    Parent := Form1;
  end; {end with}
  inc(i, 40);
end; {end button1.click}

end.

        TI



* #WhiteUnicorn/ StartPage/ Documentation/DelphiFAQ >



- - * - Anastasija aka WhiteUnicorn - * - - LJLiveJournal
PFPhotoFile