If you give a form an object reference with a name clause, such as :- DO FORM main NAME oMain
there is a real risk that the object reference oMain will go out of scope.
The code :- PUBLIC oMain DO FORM main NAME oMain
ensures that the reference will be available anywhere in your application, but has the disadvantage that it uses a PUBLIC variable.
It's also important to ensure that the object reference is immediately removed when the form no longer exists to avoid a 'dangling' object reference.
An alternative to using a PUBLIC variable is to create a forms manager by using an object.
It's beyond the scope of this FAQ as to what other uses can be made of the object.
If you need more functionality than that as discussed, try using a collection instead of an empty or custom class. You will find further help on the use of the collection class through Doug Hennig's excellent article.
In the root of your main.prg put :- oForms = CreateObject([Empty]) && VFP 8.0/9.0 or oForms = CreateObject([Custom]) && < VFP 8.0
When you launch a form, put :- AddProperty(oForms,[oMain],.NULL.) DO FORM main NAME oForms.oMain
In the .UnLoad() or other suitable terminating event of the form main put :- RemoveProperty(oForms,[oMain])
to remove the object reference.
To determine if a form exists, put :- IF VARTYPE(oForms.oMain) = [O] * Code ENDI
All one needs to remember is to prepend the form name with the object name and all the normal rules of object referencing apply.
Another benefit is that although the primary reason for the creation of the object was forms management, you now have an object that can also be used for any other purpose anywhere else in your application.
Using the Search and Replace facility of VFP it is relatively painless to convert a project to this way of working.