Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations TouchToneTommy on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

How to Detect if a Form is Open

Status
Not open for further replies.

fmoore0001

Programmer
Dec 3, 2002
192
US
Guys, does anyone have a simple routine to detect if a form is open? I would to say:

IF NOT Formopen("History")
DO FORM ("History")
ELSE
WAIT "History Form is already open..." WINDOW NOWAIT
ENDIF

Nothing I have tried seems to work to make Formopen()

Frank
 
Assuming you have only 1 form open
If _screen.ActiveForm.Name = 'History'
** form is open
else
** form not open
endif



Ali Koumaiha
TeknoSoft Inc
Farmington Hills, Michigan
 
No, I am assuming, say, 10 forms are open, the form is not the active one but I do not want to open it by mistake again.

Frank
 
I like the oldie but goodie - Window Exist Function.

IF WEXIST('myFormName')
MESSAGEBOX("It exists")
ELSE
MESSAGEBOX("No No No")
ENDIF

Jim Osieczonek
Delta Business Group, LLC
 
jimoo's solution is a good on unless there is a possibility that two forms would have the same caption then it is best to just loop through the forms via the _screen.forms() collection and check each one against a particular name. The other way to do it is to make sure you have a used the NAME clause in your Do Form commands and then you can just check the Type() of the variables and see if they are an object, ="O"

boyd.gif

craig1442@mchsi.com
"Whom computers would destroy, they must first drive mad." - Anon​
 
Craig,

I don't think that is correct. I don't think it has anything to do with the caption.

WEXIST() and WONTOP(), etc. I believe work on the name of the form.

Am I missing something?



Jim Osieczonek
Delta Business Group, LLC
 
jimoo,

I stand corrected. [blush] I usually use wexist() with toolbars and since the name always matched the caption I mistakenly assumed. Thank you for setting the record and me straight.

boyd.gif

craig1442@mchsi.com
"Whom computers would destroy, they must first drive mad." - Anon​
 
I am have some trouble with the forms trying jimoo's suggestion. I wanted to have the form found and a duplicate warning issued, so I wrote the function:

FUNCTION FormOpen
LPARAMETERS cScreenName

LOCAL lFound

lFound = .F.

IF WEXIST(cScreenName)
lFound = .T.
WAIT "This form is already open..." WINDOW NOWAIT
?? CHR(7)
ENDIF

RETURN(lFound)
ENDFUNC

where the call is:

IF NOT Formopen("history")
DO FORM ("History")
ENDIF

But it is not working. Any ideas.

Frank
 
Uhoooo. For an interesting thing. My check of:

_SCREEN.Activeform.name give a name of FORM1 the form saved as History. What name does WEXIST check against?

Frank
 
I think I need to revise my question. How do I detect if a FORM has been opened as in a DO FORM <formname>. Foxpro does not appear to have a function to do that. I want to see if the FORM by FORMNAME is currently open.

Frank
 
try this

1-add a property to form named singleopen value with .T.
2-form scx name to form name property
3-put these code below to the form load event

LOCAL x,nFormCount
nFormCount=0
* form name must be fill with scx name
* singleopen property must be on form
IF this.SingleOpen
FOR x=1 TO _screen.formcount
IF _screen.forms(x).name==this.Name
nFormCount=nFormCount+1
ENDIF
IF nFormCount>1
_screen.forms(x).show()
RETURN .f.
ENDIF
NEXT
ENDIF

Soykan OEZCELIK
 
Craig - It's not often we can correct you. You are certainly one of the TOP VFP GURUS and you have helped me a ton.



Jim Osieczonek
Delta Business Group, LLC
 
Kosta, thank you for the try, but my problem is that the NAME of the in this code is not editiable- seems to be set in a class aforehand, and so the name (Form1) is the name of several forms that may be open at the same time. You code will not work as name has to be the name of several forms. Foxpro has some way of telling the difference between them, but I have not identified it.

I was hoping to find a way to identify the DO FORM <formname> where I could identify the SCX form name when opened. This has really turned into a problem.

Frank
 
Ok fmoore0001 but i would prefer to give name property to each form of scx name this much better i think

Soykan OEZCELIK
 
It would be, but I cannot CHANGE the name property on these forms. It is locked in some way. I believe it is because a class was used to develop them, and the forms are keeping the class name 'form1'.

If that were true I could just use WEXIST(). Anyone have an idea to make the name of the form editable?

Frank
 
jimoo,

There is however something different about the way that VFP uses WEXIST() with the toolbars. I mean a form cannot have a space in it's name, but if you bring up the Report Designer toolbar and then issue the following you will see what I mean:
Code:
if WEXIST("Report Designer") and WVISIBLE("Report Designer")
     HIDE WINDOW "Report Designer"
endif

messagebox("Ok we're gonna show it again")

if WEXIST("Report Designer") and !WVISIBLE("Report Designer")
    SHOW WINDOW "Report Designer"
endif
...this is what lead me to my mistaken conclusion above. I wonder what the difference is, or if WExist() will run off the caption if it is a toolbar and off the name if it is a form? Haven't had time to try some stuff and figure this out yet.

boyd.gif

craig1442@mchsi.com
&quot;Whom computers would destroy, they must first drive mad.&quot; - Anon​
 
Very interesting... Now that I think about it the calculator and others work that way too. It is not consistent in these two case...



Jim Osieczonek
Delta Business Group, LLC
 
It's a good idea to execute the Do Form command with the name and link clause.

Unfortunately, the name property of the form will still be
the property that was set during design time.

The main problem with this, is leaving the name property to
the default value; which in many apps may be just 'Form1'.

You probably have a few apps with forms that were designed
at different times which when instantiated all have a name
property set to "Form1" :)

So, the problem with traversing the screen object and
testing the name property of each form can return an
unintended form.

Here's a possible solution, although unless the form's in
scope with the function, you probably won't be able to do
anything with it.

Darrell

Code:
Local oForm
oForm = CREATEOBJECT("form")
oform.SHOW
? IsFormOpen("oForm")
Susp


Function IsFormOpen(cFormName)
  List OBJECT TO (ADDBS(SYS(2023))+"cur_objects.txt") NOCONSOLE
  Local nHandle, bOpen, cNextLine, cObject, cObjectType
  nHandle = FOPEN(ADDBS(SYS(2023))+"cur_objects.txt")
  If nHandle<>-1
    Do WHILE !FEOF(nHandle)
      cNextLine = FGETS(nHandle)
      If LEFT(cNextLine,7) = "Object:"
        cObject = SUBSTR(cNextLine,9)
        cObjectType = SUBSTR(cObject,RAT(" ",cObject)+1)
        cObject = LEFT(cObject,AT(" ",cObject)-1)
        If cObjectType == "FORM" .AND. UPPER(cFormName)==cObject
          bOpen = .T.
          Exit
        Endif
      Endif
    Enddo
    =FCLOSE(nHandle)
  Endif
  Return bOpen
Endfunc
 
Guys, I want to thank everyone here for all their input. I finally decided on a different approach that works very well based on a number of suggestions:

First, I had to accept in this program that the former designer based the forms on a few classes. All of the classes when used as forms are IMPOSSIBLE to edit the .name property. Short of redesigning them all, and remembering that only about 20 had a problem with multiple instances running (from a menu or toolbar and modeless) I first added a property to all of the form classes:

cFormID

This immediately, of course, made the property available to all some two hundred forms based on the classes. Then, for the 20 forms with a multiple instance problem I added to the INIT method:

THISFORM.cFormID = UPPER("<myname_for_form>")

Then when calling the form

IF NOT Formopen("<myname_for_form>")
DO FORM <form_name_usually_same_as_myname_for_form>
ENDIF

Which in turn tests with the FUNCTION Formopen

FUNCTION FormOpen
LPARAMETERS cFormID

LOCAL lFound, nCount, nFormCount

lFound = .F.
nFormCount = _SCREEN.FormCount

* First, do a old fashion look for the form, if done
* via .name or DEFINE FORM
IF WEXIST(UPPER(cFormID))
lFound = .T.
WAIT "This form is already open..." WINDOW NOWAIT
?? CHR(7)
* Else check the forms current running or hidden
* Won't find released forms
ELSE
FOR nCount = 1 TO nFormCount
* See if the cFormID exists in the form being
* checked. Prevents an error if form is not based
* on one of the classes
IF PEMSTATUS(_SCREEN.Forms(nCount), "cFormID", 5)
DO CASE
* If cFormID is just set to .F., keep looking
CASE VARTYPE(_SCREEN.Forms(nCount).cFormID) ;
== "L"
* If is set to character field, check it out.
* If found, exit and report as .T. (don't
* allow another instance)
CASE _SCREEN.Forms(nCount).cFormID = ;
UPPER(cFormID)
lFound = .T.
WAIT "This form is already open..." ;
WINDOW NOWAIT
?? CHR(7)
EXIT
ENDCASE
ENDIF
NEXT
ENDIF
RETURN(lFound)
ENDFUNC

And this works beautifully! If you can, using the .name property for WEXIST would be easier if you can still do it, but this work for both situations.

Frank
 
Thought I'd throw my 2 penny's worth in. I use the forms collection and search for the form then show the form to set focus to it. It will also return the windowstate to normal (0) incase the form is minimised.

Code:
for each form in application.forms

	if upper(form.name)="FORM2" then
		form.show
		form.windowstate=0
		exit
	endif

next form

Mark Davies
Warwickshire County Council
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top