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.
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
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
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.
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... ;)
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 ;)
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.
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:
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!
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.
I personally don't use this function and don't know if it actually works or not.
Cheers,
Phil.
ASKER
Is there no problem to to nil the form
in the destroy ?
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...
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...
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.
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.
ASKER
Hi,
I'm taking this as an answer because
it's the method I use.
I'm taking this as an answer because
it's the method I use.
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.