Board index » delphi » creating and destroying forms dynamically (newbie question)

creating and destroying forms dynamically (newbie question)

Hi all,

i have a project the consists of 2 forms.  each time a button on form1 is
pressed it creates an instance of a form2.  to do this i created an array of
form2's ...

a: array of TForm2;

each button press does something like this

i := i + 1;
SetLength(a,i);
a[i - 1] := TForm2.Create(Self);
a[i - 1].Show;
a[i - 1].Caption:=IntToStr(i - 1);

i also tell each Form2 its array position number so that when it gets focus
it tells form1 it has focus.  this way i can control things on some instance
of form2 by knowing it's array position ...

j := PositionOfLastFocus; //some integer
a[j].SomeProperty := SomeValue;

anyway, whether this is the best way to this is one issue, but the bigger
issue is how to destroy instances of form2.  specifically, there are 2
things i don't know.

1. when a user closes an instance of a form2, i need to catch the closure to
do some stuff, but i also need to tell my array the form has closed, or at
least know how to check with the array position if there is a live form.
that's not very clear.  in other words, after a form2 is closed, how would i
structure an if ... then statement on the array to check if the form is
closed?

if a[j] = ? then ... ;

2. do i need to worry about memory management?  that is, if a user hits the
"X" in the upper right (of form2), assuming it changes the value in the
array (either by code on the form manually doing it or automagically -- see
the last question), do i need to do anything to prevent leaks?

thanks for any insights

-doug

 

Re:creating and destroying forms dynamically (newbie question)


Just set up an "OnClose" even in Form2 that will remove its entry from the
list, then shorten the list by one :) I'm not sure if it needs to be free'd
or not.

Nick

Quote
"dsavitsk" <dsavi...@e-coli.net> wrote in message

news:TulC8.12157$d7.4091278@newssrv26.news.prodigy.com...
Quote
> Hi all,

> i have a project the consists of 2 forms.  each time a button on form1 is
> pressed it creates an instance of a form2.  to do this i created an array
of
> form2's ...

> a: array of TForm2;

> each button press does something like this

> i := i + 1;
> SetLength(a,i);
> a[i - 1] := TForm2.Create(Self);
> a[i - 1].Show;
> a[i - 1].Caption:=IntToStr(i - 1);

> i also tell each Form2 its array position number so that when it gets
focus
> it tells form1 it has focus.  this way i can control things on some
instance
> of form2 by knowing it's array position ...

> j := PositionOfLastFocus; //some integer
> a[j].SomeProperty := SomeValue;

> anyway, whether this is the best way to this is one issue, but the bigger
> issue is how to destroy instances of form2.  specifically, there are 2
> things i don't know.

> 1. when a user closes an instance of a form2, i need to catch the closure
to
> do some stuff, but i also need to tell my array the form has closed, or at
> least know how to check with the array position if there is a live form.
> that's not very clear.  in other words, after a form2 is closed, how would
i
> structure an if ... then statement on the array to check if the form is
> closed?

> if a[j] = ? then ... ;

> 2. do i need to worry about memory management?  that is, if a user hits
the
> "X" in the upper right (of form2), assuming it changes the value in the
> array (either by code on the form manually doing it or automagically --
see
> the last question), do i need to do anything to prevent leaks?

> thanks for any insights

> -doug

Re:creating and destroying forms dynamically (newbie question)


but what if there are 10 forms open and the user closes #5?  i need some way
to trigger something to either move #10 to #5's spot and remove #10 from the
array and tell #10 that it is now #5 (fine but cumbersome), or i need to be
able to loop through the array checking for whether there are blank spots.
am i missing something?

-d

Quote
"Nicholas Sherlock" <n_sherl...@hotmail.com> wrote in message

news:abcsr1$u17$1@lust.ihug.co.nz...
Quote
> Just set up an "OnClose" even in Form2 that will remove its entry from the
> list, then shorten the list by one :) I'm not sure if it needs to be
free'd
> or not.

> Nick

> "dsavitsk" <dsavi...@e-coli.net> wrote in message
> news:TulC8.12157$d7.4091278@newssrv26.news.prodigy.com...
> > Hi all,

> > i have a project the consists of 2 forms.  each time a button on form1
is
> > pressed it creates an instance of a form2.  to do this i created an
array
> of
> > form2's ...

> > a: array of TForm2;

> > each button press does something like this

> > i := i + 1;
> > SetLength(a,i);
> > a[i - 1] := TForm2.Create(Self);
> > a[i - 1].Show;
> > a[i - 1].Caption:=IntToStr(i - 1);

> > i also tell each Form2 its array position number so that when it gets
> focus
> > it tells form1 it has focus.  this way i can control things on some
> instance
> > of form2 by knowing it's array position ...

> > j := PositionOfLastFocus; //some integer
> > a[j].SomeProperty := SomeValue;

> > anyway, whether this is the best way to this is one issue, but the
bigger
> > issue is how to destroy instances of form2.  specifically, there are 2
> > things i don't know.

> > 1. when a user closes an instance of a form2, i need to catch the
closure
> to
> > do some stuff, but i also need to tell my array the form has closed, or
at
> > least know how to check with the array position if there is a live form.
> > that's not very clear.  in other words, after a form2 is closed, how
would
> i
> > structure an if ... then statement on the array to check if the form is
> > closed?

> > if a[j] = ? then ... ;

> > 2. do i need to worry about memory management?  that is, if a user hits
> the
> > "X" in the upper right (of form2), assuming it changes the value in the
> > array (either by code on the form manually doing it or automagically --
> see
> > the last question), do i need to do anything to prevent leaks?

> > thanks for any insights

> > -doug

Re:creating and destroying forms dynamically (newbie question)


Quote
"dsavitsk" <dsavi...@e-coli.net> wrote in message

news:TulC8.12157$d7.4091278@newssrv26.news.prodigy.com...

Quote
> Hi all,

> i have a project the consists of 2 forms.  each time a button on form1 is
> pressed it creates an instance of a form2.  to do this i created an array
of
> form2's ...

> a: array of TForm2;

> each button press does something like this

> i := i + 1;
> SetLength(a,i);
> a[i - 1] := TForm2.Create(Self);
> a[i - 1].Show;
> a[i - 1].Caption:=IntToStr(i - 1);

> i also tell each Form2 its array position number so that when it gets
focus
> it tells form1 it has focus.  this way i can control things on some
instance
> of form2 by knowing it's array position ...

> j := PositionOfLastFocus; //some integer
> a[j].SomeProperty := SomeValue;

> anyway, whether this is the best way to this is one issue, but the bigger
> issue is how to destroy instances of form2.  specifically, there are 2
> things i don't know.

> 1. when a user closes an instance of a form2, i need to catch the closure
to
> do some stuff, but i also need to tell my array the form has closed, or at
> least know how to check with the array position if there is a live form.
> that's not very clear.  in other words, after a form2 is closed, how would
i
> structure an if ... then statement on the array to check if the form is
> closed?

There are several ways of handling this. A form's OnCloseQuery event can be
used to control form closure. The OnClose event can be used to do things
when a form is closed. The OnDestroy event can be used if things have to be
done when the form is destroyed - which isn't necessarily (or by default)
the same as its closure. OnClose can be used to determine what happens when
a form is closed. One of the options is that the form be destroyed.

There are a number of methods one could use to handle the notification of
form2s destruction. If you are going to destroy the form when it is closed,
i.e. you don't need to use it again, I'd suggest overriding the tForm1
Notification method and using the tForm2 Tag property to hold the array
index:

tForm1 = class (tForm)
    . . .
    protected
        procedure Notificaiton (aComponent : tComponent; Operation :
tOperation); override;
    . . .
    end;

procedure tForm1.Notification (aComponent : tComponent; Operation :
tOperation);

begin
if (not (csDestroying in ComponentState)) and (aComponent is tForm2)
then a [aComponent.Tag] := nil;    // or remove the entry from the array
inherited Notification (aComponent, Operation);
end;

In the code that creates a tForm2 instance add
    a [i - 1].Tag := i - 1;

Add an OnClose event to tForm2. In it set Action = caFree (to destroy the
form on closure). You can also add any other code that you need to. Remember
that the Tag property holds the array index.

You might want to remove the line
    a [i - 1].Caption := IntToStr (i - 1);
from tForm1 and add an OnCreate event in tForm2 that contains
    Caption := IntToStr (Tag);

Quote
> 2. do i need to worry about memory management?  that is, if a user hits
the
> "X" in the upper right (of form2), assuming it changes the value in the
> array (either by code on the form manually doing it or automagically --
see
> the last question), do i need to do anything to prevent leaks?

Since you make the form in which the tForm2 instances are created their
Owner you don't have to worry about memory leaks, since the tForm2 instances
will be destroyed when the tForm1 instance is destroyed. However if they are
not needed you may want to destroy them earlier to conserve resources.

Remember that every Delphi programmer is a component author. That's because
a form is nothing more than a complex component.

Re:creating and destroying forms dynamically (newbie question)


Thanks. That was very helpful.
-d

Quote
"Bruce Roberts" <b...@bounceitattcanada.xnet> wrote in message

news:HUmC8.11841$a04.53988@tor-nn1.netcom.ca...
Quote

> "dsavitsk" <dsavi...@e-coli.net> wrote in message
> news:TulC8.12157$d7.4091278@newssrv26.news.prodigy.com...
> > Hi all,

> > i have a project the consists of 2 forms.  each time a button on form1
is
> > pressed it creates an instance of a form2.  to do this i created an
array
> of
> > form2's ...

> > a: array of TForm2;

> > each button press does something like this

> > i := i + 1;
> > SetLength(a,i);
> > a[i - 1] := TForm2.Create(Self);
> > a[i - 1].Show;
> > a[i - 1].Caption:=IntToStr(i - 1);

> > i also tell each Form2 its array position number so that when it gets
> focus
> > it tells form1 it has focus.  this way i can control things on some
> instance
> > of form2 by knowing it's array position ...

> > j := PositionOfLastFocus; //some integer
> > a[j].SomeProperty := SomeValue;

> > anyway, whether this is the best way to this is one issue, but the
bigger
> > issue is how to destroy instances of form2.  specifically, there are 2
> > things i don't know.

> > 1. when a user closes an instance of a form2, i need to catch the
closure
> to
> > do some stuff, but i also need to tell my array the form has closed, or
at
> > least know how to check with the array position if there is a live form.
> > that's not very clear.  in other words, after a form2 is closed, how
would
> i
> > structure an if ... then statement on the array to check if the form is
> > closed?

> There are several ways of handling this. A form's OnCloseQuery event can
be
> used to control form closure. The OnClose event can be used to do things
> when a form is closed. The OnDestroy event can be used if things have to
be
> done when the form is destroyed - which isn't necessarily (or by default)
> the same as its closure. OnClose can be used to determine what happens
when
> a form is closed. One of the options is that the form be destroyed.

> There are a number of methods one could use to handle the notification of
> form2s destruction. If you are going to destroy the form when it is
closed,
> i.e. you don't need to use it again, I'd suggest overriding the tForm1
> Notification method and using the tForm2 Tag property to hold the array
> index:

> tForm1 = class (tForm)
>     . . .
>     protected
>         procedure Notificaiton (aComponent : tComponent; Operation :
> tOperation); override;
>     . . .
>     end;

> procedure tForm1.Notification (aComponent : tComponent; Operation :
> tOperation);

> begin
> if (not (csDestroying in ComponentState)) and (aComponent is tForm2)
> then a [aComponent.Tag] := nil;    // or remove the entry from the array
> inherited Notification (aComponent, Operation);
> end;

> In the code that creates a tForm2 instance add
>     a [i - 1].Tag := i - 1;

> Add an OnClose event to tForm2. In it set Action = caFree (to destroy the
> form on closure). You can also add any other code that you need to.
Remember
> that the Tag property holds the array index.

> You might want to remove the line
>     a [i - 1].Caption := IntToStr (i - 1);
> from tForm1 and add an OnCreate event in tForm2 that contains
>     Caption := IntToStr (Tag);

> > 2. do i need to worry about memory management?  that is, if a user hits
> the
> > "X" in the upper right (of form2), assuming it changes the value in the
> > array (either by code on the form manually doing it or automagically --
> see
> > the last question), do i need to do anything to prevent leaks?

> Since you make the form in which the tForm2 instances are created their
> Owner you don't have to worry about memory leaks, since the tForm2
instances
> will be destroyed when the tForm1 instance is destroyed. However if they
are
> not needed you may want to destroy them earlier to conserve resources.

> Remember that every Delphi programmer is a component author. That's
because
> a form is nothing more than a complex component.

Other Threads