Find if a form is loaded

MattWilkinson
MattWilkinson used Ask the Experts™
on
I want a method of finding out if a form is loaded or not.
I have tried things like
If frmSequence.visible then
  'do something
endif

but the call to frmSequence.visible loads it if the form is unloaded - defaeting the obective

To add a complication I can't use the API FindWindow because I have more than one form with the same caption.

Please help
Comment
Watch Question

Do more with

Expert Office
EXPERT OFFICE® is a registered trademark of EXPERTS EXCHANGE®
Ryan ChongSoftware Team Lead

Commented:
Here is a simple example, customize as you needed:

Private Sub Command2_Click()
    Dim frm As Form
    Dim isloaded As Boolean
    For Each frm In VB.Forms
        If frm.Name = "Form2" Then
            isloaded = True
        Else
            isloaded = False
        End If
    Next
    MsgBox isloaded
End Sub

Cheers

Author

Commented:
Thanks for the post, but I have two copies of the same form with the same caption, so this solution cannot tell the difference between them.

Author

Commented:
Thanks for the post, but I have two copies of the same form with the same caption, so this solution cannot tell the difference between them.
Ensure you’re charging the right price for your IT

Do you wonder if your IT business is truly profitable or if you should raise your prices? Learn how to calculate your overhead burden using our free interactive tool and use it to determine the right price for your IT services. Start calculating Now!

Commented:
Do you mean that you have created two instances of the same form ?
If yes - then I'm not sure that I understand your question.
Anyway - you need a way to distinguish between the forms. Maybe by putting a special value in the "Tag" property.
Guy Hengel [angelIII / a3]Billing Engineer
Most Valuable Expert 2014
Top Expert 2009

Commented:
You can enlarge the sample proposed, by checking the property you are looking for after you are sure that at least 1 of the forms is open:

Private Sub Command2_Click()
   Dim frm As Form
   Dim isloaded As Boolean
   isloaded = false
   For Each frm In VB.Forms
       If frm.Name = "Form2" Then
           if frm.HasSomeProperty ... then
              isloaded = True
           endif
       Else
       End If
   Next
   MsgBox isloaded
End Sub

Obviously, if it is possible for you to store the form references in global variables, this will make things much easier...

CHeers

Commented:
Hi Mat,

please try the following code

dim frm as form
for each frm in vb.forms
     if frm is nothing then
          load frm
          debug.print frm.name
          frm.visible = true      
     end if
next

Author

Commented:
To clarify.

I have two forms formA and formB
in my app load:
formA.show
set Obj1=new formB
set Obj2=new formB

Then at one point in my code I am updating the caption in all three of these forms. But I only want to update forms that are loaded (obj1 and obj2 may or may not be loaded).

So at no point are obj1 or obj2 = nothing

Author

Commented:
setting the tag property won't work either because this loads the form if it isn't loaded and I can't set this at design time because I have two instances of the same form.

Commented:
use a global collection of flags; every time you load/unload a form you set the corresponding flag in the collection! In this way you have a separate collection of form state. You won't modify the forms load status when you access the collection.
>>But I only want to update forms that are loaded

Then use the Forms collection as mentioned.  This will return a collection of loaded forms in your application.  Even though you have the variables Obj1 and Obj2 of type formB, iterating through the Forms collection you can still locate them via their .Name property.

Author

Commented:
I wanted to try and avoid adding to my (already large) data structure if possible ;-|
Guy Hengel [angelIII / a3]Billing Engineer
Most Valuable Expert 2014
Top Expert 2009

Commented:
Try this approach:

formA.show
set Obj1=new formB
obj1.visible = false
set Obj2=new formB
obj2.visible = false

Now, the forms obj1 and obj2 are "loaded", but not visible. Now you can test the .visible property safely, without risking  that the form shows up only by testing the visible property (or similar).
Note that you shouldn't have any code in the Load event if you use this technique...

CHeers
Commented:
To compare 2 Objects you need the IS operator.

This code will work i think



Dim objA As New Form2
Dim objB As New Form2

Private Sub Command1_Click()
objA.Show
End Sub

Private Sub Command2_Click()
Dim oForm As Form

For Each oForm In Forms
    If objA Is oForm Then MsgBox "found me!"
Next
End Sub
Which data structure?  It sounds as if you only want to update captions for formA objects and formB objects.  If thats the case, a simple

For Each frm In Forms
    If frm.Name = "formA" or frm.Name = "formB" Then
        UpdateCaption(frm)
    End If
Next


should be sufficient.

Commented:
Those Forms he meantion can have some pretty heavy "onLoad" statements(for example). If he does not want to fire them he needs to check if the form is loaded without checking any of the Forms properties.

He can do this by comparing the objects (objA & objB) against the objects in the Forms collection.

This can be acomplished by the IS operator. Also the NAME of the form is not a unique ID since he loads more then one. This leaves the name as an incalid choice.

The IS operator compares 2 objects and only returns true if they are the SAME INSTANCE of the same object(it compare the pointers to the objects actually).

Hope this helps...

>>If he does not want to fire them he needs to check if the form is loaded without checking any of the Forms properties.

That is why it has been suggested that he use the Forms collection, since this only returns forms that have ALREADY been loaded.


>>Also the NAME of the form is not a unique ID since he loads more then one.

But it is still unique to any instance of that form.  It should achieve the same result as using the "Is" operator.

One benefit I can see of using "Is", however, is if you ever decide to go back and rename your forms, you would have less code to go back and alter.

Commented:
Well if he accesses ObjA.Name he will create an instance of the Form (Load it). Thats what he wants to prevent. If he compares ObjA against the Forms collection then ObjA wont load  the Form. Form Objects behave a little bit different the other objects when it comes to their creation. As soon as you access any of their properties, you load the form so it can serve the property to you.

Also the Formname wont be unike...

Consider this code

Dim objA As New Form2
Dim objB As New Form2

'objA.Show
'objB.Show
debug.? forms.count 'Output will be 1
debug.? objA.name = objB.name 'this will load both forms!!! - Also it claims they are the same!!!
debug.? forms.count 'Now output will be 3 ... Bummer you just loaded 2 forms you dont want ;)
debug.? objA is ObjB 'Here it tells you they are really different

this is the difference why he would need IS instead of comparing the Names

Commented:
Remark... i commented out the objA & objB show!!! was only to lazy to delete them ;)

Hope this clears it up...
>>Well if he accesses ObjA.Name he will create an instance of the Form

But he is not accessing objA.Name.  The code posted above has always iterated over the local generic form variable as it iterates the forms in the Forms collection.  So, if objA is not loaded yet, it wont appear in the Forms collection, and we are not specifically saying objA, but using the local generic variable instead.  Again:


Dim frm As Form   'generic form variable for iterating collection

For Each frm In Forms
    'referencing the frm variable which refers to an already loaded form object
    If frm.Name = "objA" Then
        UpdateCaption(frm)
    End If
Next

Commented:
Hehe ok i overlooked that in you code... BUT

Dim objA As New Form2
Dim objB As New Form2

Private Sub Command1_Click()

Debug.Print objA.Name '---> Form2
Debug.Print objB.Name '---> Form2

So that wont help you very much! ;) - Ok you can get the Forms of the Type "Form2" but it wont help you to know if Form2 will be objA or ObjB.

Also you cannot change the Name Property of a Form. And if he wants to rename the objA form different then the ObjB Form then it wont work...

Sorry if i sound picky ;)


Commented:
Also :

MattWilkinson:Thanks for the post, but I have two copies of the same form with the same caption[Name will be the same also - rdrunner], so this solution cannot tell the difference between them.

With the IS operator you can tell them apart, and thats what was asked here ;)

and this will exactly acomplish what was asked...

Dim objA As New Form2
Dim objB As New Form2

Private Sub Command1_Click()
objA.Show
End Sub

Private Sub Command2_Click()
Dim oForm As Form

For Each oForm In Forms
   If objA Is oForm Then MsgBox "found me!"
Next
End Sub

Author

Commented:
This does what I want. I have modified it to the following:

Public Function bFormLoaded(ByVal obj As Object) As Boolean
    Dim f As Form
    For Each f In Forms
        If obj Is f Then
            bFormLoaded = True
            Exit Function
        End If
    Next
    bFormLoaded = False
End Function


Then I am calling it with:
If bFormLoaded(MyDataStructure(n).seqPane1) then MyDataStructure(n).seqPane1.caption = "New Caption"

Just to clear up again.
->I can't use oForm.Name because this returns "frmSequence" for both MyDataStructure(n).seqPane1 and MyDataStructure(n).seqPane2

->I don't want to pre-load these forms because that is the thing that is taking the time and thus the thing I want to prevent happening.

Commented:
hehe glad it works ;)
I thought the idea was to update all forms loaded of a particular type.  I didnt realize it was on a per object basis.  Glad you found a solution here.

Do more with

Expert Office
Submit tech questions to Ask the Experts™ at any time to receive solutions, advice, and new ideas from leading industry professionals.

Start 7-Day Free Trial