Link to home
Start Free TrialLog in
Avatar of jeurk
jeurk

asked on

the right way to create dynamically forms

Hi,
Can someone explain me what is the right
technic to create a form at runtime.
I mean, I want to check before if the
form already exists and if it's the case
show the one that already exists.
If assigned is not working because
when you close the form the pointer is not nilled out.
You can overide the destroy and add the
pointer:=nil in it. But I don't like it
like that.
You can also use a try catch and try to
call a method of the form. If the form does not
exist then you will get an exception.
not clean.
The clean way I found was to check
in the screen.forms list if my form
does already exist. But for that you
need to know the exact name of the
form when you do it.
How are you doing it guys ?
Thanks for your advices.
Jon.
ASKER CERTIFIED SOLUTION
Avatar of kretzschmar
kretzschmar
Flag of Germany image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of Phoenix_s
Phoenix_s

this code snippet will traverse the child components of a particular form looking for forms.  We use this to see if there are any open but hidden forms attached to a parent form before we close it.  I am sure it can be modified to look for a specific form name or instead of using the (temp is tform), you may be able to cast it to a custom form.  I am not 100% positive on this but, the syntax might be like...

if (temp is TUserForm) then ... blah blah

it works in the environment my program works with quite well and I believe it may be of some use to you

--snippet begin
{carved out of the form.closequery event}

for I := componentcount-1 downto 0 do    { scan child components from last to first }
  begin
    temp := components[i];
    if (temp is tform) then
      begin
        canclose := false;
        showmessage('Can''t close! '+components[i].name+' is still open');
        exit;
      end;

  end;    { for }


I hope this will be of some use to you.
Avatar of jeurk

ASKER

Sorry but I' not sure to understand what
you say.
I talking about checking if a form exist
before we create it. For
the moment I'm doing it like meikl says :
i := 0
while (i<screen.formcount) and Not (screen.Forms[i] is TFormSomeClass) do inc(i);
If i < screen.formcount then //form found

But i was to be sure it's the best and
cleanest and only way to do it.
I'm had that problem since too long.
well... just because I use that code snippet in a closequery event, doesn;t mean it can't be placed preceding a dynamic form create call... ;)

Avatar of jeurk

ASKER

Ok, I get the point.
Then let me tell you that I think
that this is encapsulated in the screen
object. What do you think ?
If it's the case then It's the same
solution then the one we already have.
Anyway I rejected the question to
get more opinions from others.
But thanks for your help.
Uhm. I reading again what I wrote.
don't take it wrong, I'm french
and my formulation may not be the
best ;)
I'll see what else I can discover on this topic ;)
If you don't want to call 'if Assigned(Form1) then' you can replace variable with function with same name which will create instance of form.
For example
Instead of
  TForm1=class(TForm)
.........
var
  Form1: TForm1;
....
you can write
  TForm1=class(TForm)
........
function Form1: TForm1;

implementation
var
  Form1Var: TForm1;
function Form1: TForm1;
begin
  if not Assigned(Form1Var) then
    Form1Var := TForm1.Create(Application);
  Result := Form1Var;
end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
  Form1Var := nil;
end;

In the main program instead of 'if Assigned(Form1) then' you can simply write Form1.FormMethod - Form1 will be created automatically.
Vladika :

looks like a neat idea... but it seems like it would only create forms as children of the application

where in some cases it might be prudent to make the new form a child of an already open form... that way it might be easier to step through a form's components to locate the 'offending' form instead of trolling though the entire application heirarchy

I imagine your idea could be convoluted to act in the manner I outlined above..

cheers!
Just my two cents but a nasty hack for the "freed but pointer not nil" problem could be to use IsBadReadPtr().

I personally don't use this function and don't know if it actually works or not.

Cheers,
Phil.
Avatar of jeurk

ASKER

Is there no problem to to nil the form
in the destroy ?
If you have D5 use FreeAndNil - if not use this ;-)

procedure FreeAndNil(var Obj);
var
  P: TObject;
begin
  P := TObject(Obj);
  TObject(Obj) := nil;  // clear the reference before destroying the object
  P.Free;
end;

Regards

PS. Nil pointers are the "cleanest" way IMHO...
Avatar of jeurk

ASKER

Anaway,
I can see that there is not one right way
to do this. This should be done in standard
by borland.
I think I'm gonna do it by checking in
the screen.forms list if my form is
already there or not.
The freeand nil is not ok because
my forms are not modal and it's
not easy to handle.
Avatar of jeurk

ASKER

Hi,
I'm taking this as an answer because
it's the method I use.