Board index » delphi » Creating forms at runtime / Multiple Instances of 1 form

Creating forms at runtime / Multiple Instances of 1 form

Hi all

I am building an application (D5) which has a large number of forms, but
only some of those forms will be used each time the application is opened.
In addition I want the user to be able to open multiple instances of some of
the forms.

The user may close and re-open any particular form a number of times while
using the application.

I have removed all the lines like
    Application.CreateForm(TForm1, Form1);
from the main program code except in the case of the MDI parent and one
other form, so that these forms will not be created at startup.

In all the child forms, I've set "Action := caFree" in the FormClose event.

In the button on the MDI parent which will open/re-open a form I have:

  if not assigned(form1) then form1 := Tform1.Create(Application);
  form1.Show;

All works well the first time that each form is created at runtime.

However if any of the forms which are created at runtime are closed and
re-opened, then there is an "Access violation at address ..." error.

When I have tried to trace the error, it appears that the pointer for the
form is not being set to nil after the form is closed (Tform.free ??)
ie the form's pointer isn't nil but it no longer points to valid data.

Is this how Delphi is intended to work (when the formclose event action is
set to caFree), and if so what is the best way of applying the "freeandnil"
routine to a form, when the user initiates a form close.

Many thanks for any help

Mike
Melbourne, Australia

 

Re:Creating forms at runtime / Multiple Instances of 1 form


Delphi does *not* set a reference to a Form to Nil when the form is
closed

You have to do that yourself.

Without seeing your code it is not easy to suggest the 'best' way of
setting the Form1 variable to Nil

On Sat, 7 Dec 2002 12:15:01 +1100, "Mike Manning"

Quote
<mpmann...@optusnet.com.au> wrote:
>Hi all

>I am building an application (D5) which has a large number of forms, but
>only some of those forms will be used each time the application is opened.
>In addition I want the user to be able to open multiple instances of some of
>the forms.

>The user may close and re-open any particular form a number of times while
>using the application.

>I have removed all the lines like
>    Application.CreateForm(TForm1, Form1);
>from the main program code except in the case of the MDI parent and one
>other form, so that these forms will not be created at startup.

>In all the child forms, I've set "Action := caFree" in the FormClose event.

>In the button on the MDI parent which will open/re-open a form I have:

>  if not assigned(form1) then form1 := Tform1.Create(Application);
>  form1.Show;

>All works well the first time that each form is created at runtime.

>However if any of the forms which are created at runtime are closed and
>re-opened, then there is an "Access violation at address ..." error.

>When I have tried to trace the error, it appears that the pointer for the
>form is not being set to nil after the form is closed (Tform.free ??)
>ie the form's pointer isn't nil but it no longer points to valid data.

>Is this how Delphi is intended to work (when the formclose event action is
>set to caFree), and if so what is the best way of applying the "freeandnil"
>routine to a form, when the user initiates a form close.

>Many thanks for any help

>Mike
>Melbourne, Australia

Re:Creating forms at runtime / Multiple Instances of 1 form


Quote
"Mike Manning" <mpmann...@optusnet.com.au> wrote in message
> Is this how Delphi is intended to work (when the formclose event action is
> set to caFree), and if so what is the best way of applying the
"freeandnil"
> routine to a form, when the user initiates a form close.

Yes. In Delphi a form is just another object. IMO your best bet is to not
use the form variables automatically added by Delphi. Instead use the
Screen.CustomForms property:

function GetFormInstance (aClass : tFormClass; aOwner : tComponent) :
tCustomForm;

var i : integer;

begin
i := Screen.CustomFormCount - 1;
while (i >= 0) and (not (Screen.CustomForms [i] is aClass)) do
    dec (i);
if i < 0
then result := aClass.Create (aOwner)
else result := Screen.CustomForms [i];
end;

Re:Creating forms at runtime / Multiple Instances of 1 form


Thanks for response
Just curious - why does Delphi not set the reference to nil if the object's
free method has been called ?

Mike M

Quote
"J French" <Bounce_It_je...@iss.u-net.com_.bin> wrote in message

news:3df1b413.4030409@news.u-net.com...
Quote
> Delphi does *not* set a reference to a Form to Nil when the form is
> closed

> You have to do that yourself.

> Without seeing your code it is not easy to suggest the 'best' way of
> setting the Form1 variable to Nil

> On Sat, 7 Dec 2002 12:15:01 +1100, "Mike Manning"
> <mpmann...@optusnet.com.au> wrote:

> >Hi all

> >I am building an application (D5) which has a large number of forms, but
> >only some of those forms will be used each time the application is
opened.
> >In addition I want the user to be able to open multiple instances of some
of
> >the forms.

> >The user may close and re-open any particular form a number of times
while
> >using the application.

> >I have removed all the lines like
> >    Application.CreateForm(TForm1, Form1);
> >from the main program code except in the case of the MDI parent and one
> >other form, so that these forms will not be created at startup.

> >In all the child forms, I've set "Action := caFree" in the FormClose
event.

> >In the button on the MDI parent which will open/re-open a form I have:

> >  if not assigned(form1) then form1 := Tform1.Create(Application);
> >  form1.Show;

> >All works well the first time that each form is created at runtime.

> >However if any of the forms which are created at runtime are closed and
> >re-opened, then there is an "Access violation at address ..." error.

> >When I have tried to trace the error, it appears that the pointer for the
> >form is not being set to nil after the form is closed (Tform.free ??)
> >ie the form's pointer isn't nil but it no longer points to valid data.

> >Is this how Delphi is intended to work (when the formclose event action
is
> >set to caFree), and if so what is the best way of applying the
"freeandnil"
> >routine to a form, when the user initiates a form close.

> >Many thanks for any help

> >Mike
> >Melbourne, Australia

Re:Creating forms at runtime / Multiple Instances of 1 form


Quote
"Mike Manning" <mpmann...@optusnet.com.au> wrote in message

news:3dfdce1a$0$5415$afc38c87@news.optusnet.com.au...

Quote
> Thanks for response
> Just curious - why does Delphi not set the reference to nil if the
object's
> free method has been called ?

Because the instance has no idea what if any references there are to it.

Re:Creating forms at runtime / Multiple Instances of 1 form


Quote
Mike Manning wrote in message

<3dfdce1a$0$5415$afc38...@news.optusnet.com.au>...

Quote
>Thanks for response
>Just curious - why does Delphi not set the reference to nil if the
object's
>free method has been called ?

var a, b: tobject;
begin
  a:=tlist.create;
  b:=a;
  a.free;
end;

Should freeing a clear a? Should it clear b?

var a, b, c: tobject; d: integer;
begin
  a:=tlist.create;
  b:=tstringlist.create;
  readln(d);
  if (d=0) then c:=a else c:=b;
  a.free;
end;

Should freeing a clear a? b? c? How will you know?

That's the real question in any case: how will you know?
Think what needs to happen to "do the right thing" when
you typed "1", or "0", or "a".

Groetjes,
Maarten Wiltink

Re:Creating forms at runtime / Multiple Instances of 1 form


Thanks for your help Maarten / Bruce - Answer is obvious when explained like
that !

Quote
"Maarten Wiltink" <maar...@kittensandcats.net> wrote in message

news:3dfe5406$0$88856$e4fe514c@news.xs4all.nl...
Quote
> Mike Manning wrote in message
> <3dfdce1a$0$5415$afc38...@news.optusnet.com.au>...
> >Thanks for response
> >Just curious - why does Delphi not set the reference to nil if the
> object's
> >free method has been called ?

> var a, b: tobject;
> begin
>   a:=tlist.create;
>   b:=a;
>   a.free;
> end;

> Should freeing a clear a? Should it clear b?

> var a, b, c: tobject; d: integer;
> begin
>   a:=tlist.create;
>   b:=tstringlist.create;
>   readln(d);
>   if (d=0) then c:=a else c:=b;
>   a.free;
> end;

> Should freeing a clear a? b? c? How will you know?

> That's the real question in any case: how will you know?
> Think what needs to happen to "do the right thing" when
> you typed "1", or "0", or "a".

> Groetjes,
> Maarten Wiltink

Other Threads