Solved

Using an if statement in Delphi 2006 to determine if a form exists

Posted on 2007-03-22
34
1,311 Views
Last Modified: 2013-11-23
I have a form (frmNewStudentSelect) and would like to know how, within an if statement, to determine if the form exists.

0
Comment
Question by:wbstech
  • 12
  • 11
  • 4
  • +4
34 Comments
 
LVL 21

Expert Comment

by:ziolko
ID: 18769974
if Assigned(frmNewStudentSelect) then

ziolko.
0
 
LVL 21

Expert Comment

by:ziolko
ID: 18769985
what's important... use FreeAndNil() to dispose form when no longer needed
and :

procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
  Action := caFree;
end;

when form is MDI child

ziolko.
0
 
LVL 28

Expert Comment

by:ciuly
ID: 18773258
and something that never fails:

function formExists(form:TForm):boolean;
begin
  try
    if form.visible then;// just access a member. will through an AV if teh form does not exist
    result:=true;
  except
    result:=false;
  end;
end;

and use like
if formexists(frmNewStudentSelect) then
  blabla

this way you don't need to use freeandnil (though a good idea, I for example never used it :) so if you're in my case you'd like to use a method that doesn't rely on using it, until you get used to using it (this sounds "weird" :) ))
0
 
LVL 10

Accepted Solution

by:
dinilud earned 500 total points
ID: 18778069
ciuly your idea would't work.
try this and check.

First Button click will fine. What about second time


unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls;

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

var
  Form1: TForm1;
  x:TForm1;
implementation

{$R *.dfm}

function TForm1.formExists(form:TForm):boolean;
begin
  try
    if form.visible then;// just access a member. will through an AV if teh form does not exist
    result:=true;
  except
    result:=false;
  end;
end;


procedure TForm1.Button1Click(Sender: TObject);
begin
   if not formExists(X) then
         x:=TForm1.Create(Self);
   X.ShowModal;
   X.Free;
end;

end.
0
 
LVL 21

Expert Comment

by:ziolko
ID: 18778160
why not this way?

procedure TForm1.Button1Click(Sender: TObject);
begin
   if not Assigned(X) then
         x := TForm2.Create(Self);
   X.ShowModal;
   FreeAndNil(x);
end;

ziolko.
0
 
LVL 28

Expert Comment

by:ciuly
ID: 18778168
dinilud: the example code works just fine. it's you that not payed attention :)
try debugging it. put a breakpoint on the if not formextss line and run teh application. first click, you step over with F8, you'll notice that X is created. second click, step over you'll notice that X is no longer created. the error you get is because you used showmodal and x is already showing modal so can't do that again ;)
0
 
LVL 28

Expert Comment

by:ciuly
ID: 18778170
also, I would like to make it clear if I didn't in my first post, that the *preffered* way is the one pointed out by ziolko. but not many are using it (me included :D )
0
 
LVL 21

Expert Comment

by:ziolko
ID: 18778227
to be more specific, i would do it this way:

procedure TForm1.Button1Click(Sender: TObject);
begin
  try
     if not Assigned(X) then
         x := TForm2.Create(Self);
     X.ShowModal;
   finally
     FreeAndNil(x);
   end;
end;

you never know whats gonna happen when you call ShowModal:)

ziolko.
0
 
LVL 10

Expert Comment

by:dinilud
ID: 18778365
Ciuly:

procedure TfrmNewStudentSelect.FormClose(Sender: TObject; var Action: TCloseAction);
begin
  Action:=caHide;
end;

after exicuting this line,the memory must free and the pointer is not nil.
So Second time if you call your formExists function this will give false information.
(using watch window you can check)

i think your code will work only when pointer(means frmNewStudentSelect) is nil

ziolko:
Your Code will work perfectly when we use use ShowModel.
if you use show is it works fine?.
0
 
LVL 10

Expert Comment

by:dinilud
ID: 18778376
procedure TfrmNewStudentSelect.FormClose(Sender: TObject; var Action: TCloseAction);
begin
  Action:=caHide;
  frmNewStudentSelect:=nil;
end;

.......

if not assigned(frmNewStudentSelect) then
  frmNewStudentSelect:=TfrmNewStudentSelect.create(self);

frmNewStudentSelect.show;
0
 
LVL 21

Expert Comment

by:ziolko
ID: 18778382
if you use Show instead ShowModal
it's your responsibility to make sure that reference to form will be set to nil

when you use exactly this code:

  try
     if not Assigned(X) then
         x := TForm2.Create(Self);
     X.Show;
   finally
     FreeAndNil(x);
   end;

you won't be able to even see form as it will be released immidietly after creating


ziolko
0
 
LVL 10

Expert Comment

by:dinilud
ID: 18778386
is my code is working?
0
 
LVL 21

Expert Comment

by:ziolko
ID: 18778391
never ever do this:

frmNewStudentSelect:=nil;

in event handler of frmNewStudentSelect

i think it will be a lot easier for us if you write what you trying achieve
hiding form is not same as releasing it

ziolko.





0
 
LVL 21

Expert Comment

by:ziolko
ID: 18778408
if you want only show/hide form in non-modal way simply go to project options and add it to autocreate section then use .Show .Hide

if you want create/destroy form use Assigned(), Create(), FreeAndNil() combination

ziolko.
0
 
LVL 10

Expert Comment

by:dinilud
ID: 18778419
if form is MDI Chid what we will do?.  MDIChild form we can't hide.
0
 
LVL 21

Expert Comment

by:ziolko
ID: 18778438
ahhh if it's MDI child then use:

procedure TfrmNewStudentSelect.FormClose(Sender: TObject; var Action: TCloseAction);
begin
  Action:=caFree;
end;

and if you want check if it exists use

MDIParentForm.MDIChildCount
MDIParentForm.MDIChildren[i]

to browse thru all MDI children

ziolko.
0
 
LVL 10

Expert Comment

by:dinilud
ID: 18778505
ziolko.

procedure TfrmNewStudentSelect.FormClose(Sender: TObject; var Action: TCloseAction);
begin
  Action:=caFree;
  frmNewStudentSelect:=nil;
  ShowMessage(Caption);
end;

This Code Shows Caption. Means Self is not released yet.
I think, The close event is generated by Self not frmNewStudentSelect.

So I think this code has no problem.

if my concept is wrong please Correct me. its my request to every body
0
IT, Stop Being Called Into Every Meeting

Highfive is so simple that setting up every meeting room takes just minutes and every employee will be able to start or join a call from any room with ease. Never be called into a meeting just to get it started again. This is how video conferencing should work!

 
LVL 28

Expert Comment

by:ciuly
ID: 18778517
dinilud: I have no idea why the code is not workign properly. it should. it is probably some "thing" in the borland implementation of the OO part, since once an object is freed, all memory associated with it should be freed as well, however, the object is still usable (partly). I'm guessing it has something to do with the COM layer, since all (?) delphi objects are also COM objects.


if you do the following:

  showmessage(inttostr(x.InstanceSize));
  x.free;
  showmessage(inttostr(x.InstanceSize));

you will see a very weird behaviour there, since the instance size after freeing will be a big (random?) number, in any case different than before freeing. so something happens along the way but I don't know what.

I think I'll open up a question to clarify this since I am curious why this happens :)
0
 
LVL 10

Expert Comment

by:dinilud
ID: 18778530
OK good idea for MDI Child. Thank you for your valuable information.
0
 
LVL 21

Expert Comment

by:ziolko
ID: 18778619
>>This Code Shows Caption. Means Self is not released yet.

nope form is not released yet in OnCloseEvent handler since this event is called as one of
routines during object destruction, but general rule is that assign nil after object is completely destroyed
(object not interface) from my exp. assignin nil to object within it's event handler will make some f*** up sooner or later

>>I think, The close event is generated by Self not frmNewStudentSelect.

I assume that frmNewStudentSelect is defined as
var frmNewStudentSelect: TfrmNewStudentSelect;
in same unit where whole def. of TfrmNewStudentSelect;
if so Self = frmNewStudentSelect
or maybe frmNewStudentSelect is declared somwhere else?

ziolko.
0
 
LVL 10

Expert Comment

by:dinilud
ID: 18778703
Ciuly:

  i know my language is very bad. Sorry for that.

    I don't no any thing aboult COM Layer.
    I think the form is freeing and memomory also relasing. But The object pointer is not setting nil.  
    So i think, if we try  to access that object again, program will assume the object is there because that pointer is not nil. So we get that random number as the instend size. I am also not sure is my concept is currect or not.
0
 
LVL 10

Expert Comment

by:dinilud
ID: 18778735
ziolko.


>>I assume that frmNewStudentSelect is defined as
>>var frmNewStudentSelect: TfrmNewStudentSelect;
>>in same unit where whole def. of TfrmNewStudentSelect;
>>if so Self = frmNewStudentSelect
>>or maybe frmNewStudentSelect is declared somwhere else?

Then i think in your compilier this also works!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

procedure TfrmNewStudentSelect.FormClose(Sender: TObject; var Action: TCloseAction);
begin
  Action:=caFree;
  frmNewStudentSelect:=nil;
  ShowMessage(Caption);
  ShowMessage(frmNewStudentSelect.Caption);
end;




0
 
LVL 10

Expert Comment

by:dinilud
ID: 18778762
ziolko.
   is my code is working?. if i hurt you i am asking you sorry. Once again i am telling I AM NOT EXPERT IN ENGLISH. I AM A PURE MALAYALEE( from KERALA).
0
 
LVL 21

Expert Comment

by:ziolko
ID: 18778900
heh dinilud no dramma mate i'm not hurt:)

but then can we go back to the point?
dinilud can you describe (dont worry about english:)) what are you exactly trying to do?

ziolko.
0
 
LVL 10

Expert Comment

by:dinilud
ID: 18778963

Through argument i am building my knowledge.
 i am not care about points.
i am also using your first way using showmodel. i tried to clarify my some doubt. thats all.
0
 
LVL 21

Expert Comment

by:ziolko
ID: 18779148
so no specific task or problem just trying to learn something new?

ziolko.
0
 
LVL 6

Expert Comment

by:House_of_Dexter
ID: 18813189
k...

procedure TfrmNewStudentSelect.FormClose(Sender: TObject; var Action: TCloseAction);
begin
  Action:=caFree; //<-after this event fires...FormClose post a message back to Self to free
  frmNewStudentSelect:=nil; //this is fine...as long as you check if frmNewStudentSelect is assigned before calling it...
  ShowMessage(Caption);//no prob Self is still active and not freed yet
  ShowMessage(frmNewStudentSelect.Caption);//AcessViolation frmNewStudentSelect is nill
end;

k...lets understand Forms...

when you call Close this happens

procedure TCustomForm.Close;
var
  CloseAction: TCloseAction;
begin
  if fsModal in FFormState then
    ModalResult := mrCancel
  else
    if CloseQuery then
    begin
      if FormStyle = fsMDIChild then
        if biMinimize in BorderIcons then
          CloseAction := caMinimize else
          CloseAction := caNone
      else
        CloseAction := caHide;
      DoClose(CloseAction);//<----this is your FormClose
      if CloseAction <> caNone then
        if Application.MainForm = Self then Application.Terminate
        else if CloseAction = caHide then Hide
        else if CloseAction = caMinimize then WindowState := wsMinimized
        else Release;//<--this is the most important part...this is what happens when you set to caFree
    end;
end;

{your on FormClose which is called in  TCustomForm.Close
procedure TCustomForm.DoClose(var Action: TCloseAction);
begin
  if Assigned(FOnClose) then FOnClose(Self, Action);
end;
}

which calls

procedure TCustomForm.Release;
begin
  PostMessage(Handle, CM_RELEASE, 0, 0);
end;

which calls

procedure TCustomForm.CMRelease;
begin
  Free;
end;

the beauty of this is that any messages that are still in the the queue will be handled...meaning Self is still good until we get to CMRelease...



0
 
LVL 17

Expert Comment

by:Wim ten Brink
ID: 18814897
Can I suggest a much simp-ler solution? Why not walk through the Screen.CustomForms array and check if Screen.CustomForms[Index] is frmNewStudentSelect?

Something like:

function HasfrmNewStudentSelect: Boolean;
var I:Integer;
begin
  I := Pred(Screen.CustomFormCount);
  while (I > 0) and not Screen.CustomForms[I] is TfrmNewStudentSelect do Dec(I);
  Result := (I > 0);
end;

If your form is active, it will be listed in this array. Else it is not. :-)
0
 
LVL 1

Expert Comment

by:swiatlo
ID: 18858382
If you create all your forms with the same owner ie. MyForm.Create(Application). you could iterate through Application/Owner components to find out if it has it already.

result :=false
for i:=0 to ComponentCount-1 do
begin
  if MyOwner.Components[i].ClassName = 'TfrmNewStudentSelect' then
   {result:=true, break }
{
Or
  if MyOwner.Components[i].Name = 'frmNewStudentSelect' then result true, break }            
end
            
0
 
LVL 1

Expert Comment

by:swiatlo
ID: 18858494
Or simply
if MyOwner.Components[i] is TfrmNewStudentSelect then
  {result:=true, break }
0
 
LVL 17

Expert Comment

by:Wim ten Brink
ID: 18862729
swiatlo, your solution will work but is less reliable since it requires forms to be created with some owner. However, all forms will be part of the Screen.CustomForms list because they all add themselves to Screen.

Also, "MyOwner.Components[i].ClassName = 'TfrmNewStudentSelect'"... WTF??? You do realise that comparing strings in Delphi will be a lot slower than just checking the class type? :-)

Finally, while you can use for/break to walk through the list, in this case it's just better to use a while loop instead because the code tends to be slightly cleaner in the eyes of Pascal Puritanists. In general, things like label/goto/break/continue/exit are considered signs of bad programming by some developers, including me, because they make it less clear when a loop/procedure will exit.

One fix on my code, btw... This line:
Result := (I > 0);
should be replaced with:
Result := (Screen.CustomForms[I] is TfrmNewStudentSelect);
Or you should replace > with >=
0
 
LVL 1

Expert Comment

by:bhavesh_joshi
ID: 18944427
if Assigned(frmNewStudentSelect) then ShowMessage('Created') else showmessage('Not created');

and if you want to know if its visible

if frmNewStudentSelect.visible then ShowMessage('Form is Visible') else showmessage('Form is InVisible')
0
 
LVL 1

Expert Comment

by:bhavesh_joshi
ID: 18944436
if Assigned(frmNewStudentSelect) then ShowMessage('Created') else showmessage('Not created');

and if you want to know if its visible

if frmNewStudentSelect.visible then ShowMessage('Form is Visible') else showmessage('Form is InVisible')

or

if frmNewStudentSelect.Showing then ShowMessage('Form is Showing) else showmessage('Form is Hidden')
0
 
LVL 21

Expert Comment

by:ziolko
ID: 18944766
bhavesh_joshi all your comments were previously posted here

anyways wbstech i'm not pushig you but maybe it's time to close this Q?:)

ziolko.
0

Featured Post

How your wiki can always stay up-to-date

Quip doubles as a “living” wiki and a project management tool that evolves with your organization. As you finish projects in Quip, the work remains, easily accessible to all team members, new and old.
- Increase transparency
- Onboard new hires faster
- Access from mobile/offline

Join & Write a Comment

Suggested Solutions

In my programming career I have only very rarely run into situations where operator overloading would be of any use in my work.  Normally those situations involved math with either overly large numbers (hundreds of thousands of digits or accuracy re…
Jaspersoft Studio is a plugin for Eclipse that lets you create reports from a datasource.  In this article, we'll go over creating a report from a default template and setting up a datasource that connects to your database.
The viewer will learn how to use and create keystrokes in Netbeans IDE 8.0 for Windows.
The viewer will learn how to synchronize PHP projects with a remote server in NetBeans IDE 8.0 for Windows.

743 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

12 Experts available now in Live!

Get 1:1 Help Now