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 Chris Miller on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Acess form's custom properties from menu? 4

Status
Not open for further replies.

Paco75

Programmer
Oct 11, 2001
239
US
Hi,

I have a standalone form with a menu and i want to acess my custom properties i put in the form but i can`t manage to do a call like
Code:
thisform.myProperty = "TEST"

So i need to pass a variable from menu to standalone form!

anyone know how to? except than putting the property as public variable :(
 
You need to create a local variable, and use it to store an object reference to the form. Do that in the code that creates the menu.

I know you are using the menu designer to create your menu, so you might have to hand-modify the menu code, or create the entire menu in code, using the generated code as a guide.

Something like this:

Code:
LOCAL loForm
loForm = THISFORM 

DEFINE BAR 1 ....
ON SELECTION BAR 1 OF ... loForm.SomeMethod

If you want to access a property in a clause of the DEFINE BAR (such as the SKIP FOR clause), you need to make the variable PRIVATE:

Code:
PRIVATE poFom
poForm = THISFORM

DEFINE BAR 1 ... SKIP FOR poForm.NotAvailable

Does that give you the general idea?

Mike


__________________________________
Mike Lewis (Edinburgh, Scotland)

Visual FoxPro articles, tips, training, consultancy
 
Menu code exists "outside" the form object so you can't use "thisform". Only code that's inside an object can make reference to itself.

You can create a variable just for the purpose as Mike suggests. Or your menu code can reference _Screen.Activeform instead of Thisform. The caveat is that you need to make sure the menu won't ever make that reference when Activeform is empty.

(You can creatively use SKIP FOR to disable menu options when there isn't an Activeform, for example.)
 
i get the error "Thisform can only be used within a method
 
i also tried _Screen.Activeform but i dont have access to form.

here is my .mpr file
Code:
LPARAMETERS oFormRef, getMenuName, lUniquePopups, parm4, parm5, parm6, parm7, parm8, parm9
LOCAL cMenuName, nTotPops, a_menupops, cTypeParm2, cSaveFormName
 
IF TYPE("m.oFormRef") # "O" OR ;
  LOWER(m.oFormRef.BaseClass) # 'form' OR ;
  m.oFormRef.ShowWindow # 2
	MESSAGEBOX([This menu can only be called from a Top-Level form. Ensure that your form's ShowWindow property is set to 2. Read the header section of the menu's MPR file for more details.])
	RETURN
ENDIF
m.cTypeParm2 = TYPE("m.getMenuName")
m.cMenuName = SYS(2015)
m.cSaveFormName = m.oFormRef.Name
IF m.cTypeParm2 = "C" OR (m.cTypeParm2 = "L" AND m.getMenuName)
	m.oFormRef.Name = m.cMenuName
ENDIF
IF m.cTypeParm2 = "C" AND !EMPTY(m.getMenuName)
	m.cMenuName = m.getMenuName
ENDIF
DIMENSION a_menupops[1]
IF TYPE("m.lUniquePopups")="L" AND m.lUniquePopups
	FOR nTotPops = 1 TO ALEN(a_menupops)
		a_menupops[m.nTotPops]= SYS(2015)
	ENDFOR
ELSE
	a_menupops[1]="newitem"
ENDIF


*       *********************************************************
*       *                                                         
*       *                      Menu Definition                    
*       *                                                         
*       *********************************************************
*

DEFINE MENU (m.cMenuName) IN (m.oFormRef.Name) BAR

DEFINE PAD _3h70uffqt OF (m.cMenuName) PROMPT "\<Fichier" COLOR SCHEME 3 ;
	KEY ALT+F, "ALT+F"
ON PAD _3h70uffqt OF (m.cMenuName) ACTIVATE POPUP (a_menupops[1])

DEFINE POPUP (a_menupops[1]) MARGIN RELATIVE SHADOW COLOR SCHEME 4
DEFINE BAR 1 OF (a_menupops[1]) PROMPT "Ouvrir \<Estime" ;
	KEY CTRL+E, "CTRL+E"
DEFINE BAR 2 OF (a_menupops[1]) PROMPT "Ouvrir \<Bon de Commande" ;
	KEY CTRL+C, "CTRL+C"
DEFINE BAR 3 OF (a_menupops[1]) PROMPT "Ouvrir \<Bon de Production" ;
	KEY CTRL+P, "CTRL+P"
ON SELECTION BAR 1 OF (a_menupops[1]) ;
	DO _3h70uffqu ;
	IN LOCFILE("VISUALINSPECTOR\MENUPRINCIPAL" ,"MPX;MPR|FXP;PRG" ,"WHERE is MENUPRINCIPAL?")
ON SELECTION BAR 2 OF (a_menupops[1]) ;
	DO _3h70uffqv ;
	IN LOCFILE("VISUALINSPECTOR\MENUPRINCIPAL" ,"MPX;MPR|FXP;PRG" ,"WHERE is MENUPRINCIPAL?")
ON SELECTION BAR 3 OF (a_menupops[1]) ;
	DO _3h70uffqw ;
	IN LOCFILE("VISUALINSPECTOR\MENUPRINCIPAL" ,"MPX;MPR|FXP;PRG" ,"WHERE is MENUPRINCIPAL?")

ACTIVATE MENU (m.cMenuName) NOWAIT

IF m.cTypeParm2 = "C"
	m.getMenuName = m.cMenuName
	m.oFormRef.Name = m.cSaveFormName 
ENDIF

***************************************************
PROCEDURE _3h70uffqu

LOCAL loForm
loForm = _Screen.Activeform
DO FORM frmOpenEstimate
loForm.lblEstimateNo.caption = "Test"

In the last procedure you can see what im trying to do.
 
1. Do not attempt to use _Screen.Activeform when there isn't any form. I thought I said that.

2. You have removed from your generated code the standard comments for using your top-level menu with a form. I'll paste them here:

Code:
* To attach this menu to your Top-Level form, 
* call it from the Init event of the form:

* Syntax: DO <mprname> WITH <oFormRef> [,<cMenuname>|<lRename>][<lUniquePopups>]

*	oFormRef - form object reference (THIS)
*	cMenuname - name for menu (this is required for Append menus - see below)
*	lRename - renames Name property of your form
*	lUniquePopups - determines whether to generate unique ids for popup names
			
* 	example:

*	PROCEDURE Init
*		DO mymenu.mpr WITH THIS,.T.
*	ENDPROC

* Use the optional 2nd parameter if you plan on running multiple instances
* of your Top-Level form. The preferred method is to create an empty string
* variable and pass it by reference so you can receive the form name after
* the MPR file is run. You can later use this reference to destroy the menu.

 
Paco,

To use the code I gave you, you will need to create the menu in a method of the form. I know from your other question that the menu is part of your top-level form, so there should be nothing to prevent you from creating the menu in the Load or Init of that form, in which case you won't get the "Thisform can only be used within a method" error.

Mike

__________________________________
Mike Lewis (Edinburgh, Scotland)

Visual FoxPro articles, tips, training, consultancy
 
LOCAL loForm
loForm = _Screen.Activeform <- trying to access a form here
DO FORM frmOpenEstimate <- while you create it here

Does this make sense?

Turn the command order arund:
1. create a form
2. set it's properties

You can't set properties of something not existing yet, can you?

Bye, Olaf.
 
Besides I would suggest the form should set it's caption itself. Play by the rules of OOP, encapsulation is important, a class, and also a standard SCX form, shold be self contained, mostly.

Why do you need to set the form caption from the menu?

Bye, Olaf.
 
I did like Mike suggested and created the menu in a method of the top level form. I choosed form.Activate here is the code.

Code:
CLEAR
SET SYSMENU SAVE
SET SYSMENU TO
ON KEY LABEL ESC KEYBOARD CHR(13)
DEFINE MENU mainMenu BAR in window frmMain
DEFINE PAD padFile OF mainMenu PROMPT '\<File' COLOR SCHEME 3 KEY ALT+F, ''
ON PAD padFile OF mainMenu ACTIVATE POPUP popFile
DEFINE POPUP popFile MARGIN RELATIVE SHADOW COLOR SCHEME 4
DEFINE BAR 1 OF popFile PROMPT "Open \<Estimate" KEY CTRL+E, "CTRL+E"
DEFINE BAR 2 OF popFile PROMPT "Ouvrir \<Purchase Order" KEY CTRL+O, "CTRL+O"
DEFINE BAR 3 OF popFile PROMPT "Ouvrir \<Production Order" KEY CTRL+P, "CTRL+P"
ON SELECTION BAR 1 OF popFile ;
	thisform.openEstimate 
ON SELECTION BAR 2 OF popFile ;
	thisform.openPurchOrd
ON SELECTION BAR 3 OF popFile ;
	thisform.openProdOrd
ACTIVATE MENU mainMenu nowait

and on form unload of top level form

Code:
DEACTIVATE MENU mainMenu 
RELEASE MENU mainMenu EXTENDED
SET SYSMENU TO DEFAULT

But the menu still work as before... thisform (the toplevel form) is not accessible from menu. Im not sure im explaining myself clearly...

When user press File->Open estimate it pops a small window to ask user the estimate number. Then i want to return that value to the top level form so i could fill the form's objects (textfields, combobox,... etc) to do this i must have acces to top level form.

The menu is loaded in the top level form and the form is visible and active (otherwise i would not see the menu that is loaded in) so logically i should be able to access the components of the form that contains the menu!
 
You're never going to be able to use ThisForm in menu code. What both Mike and Olaf were suggesting were ways to get a reference to the form inside the menu, so you don't need ThisForm.

My experience is that I can almost always use _Screen.ActiveForm rather than ThisForm in menu code.

Tamar
 
Thanks it worked with _Screen.ActiveForm directly in replacement of thisform.

Code:
CLEAR
SET SYSMENU SAVE
SET SYSMENU TO
ON KEY LABEL ESC KEYBOARD CHR(13)
DEFINE MENU mainMenu BAR in window frmMain
DEFINE PAD padFile OF mainMenu PROMPT '\<File' COLOR SCHEME 3 KEY ALT+F, ''
ON PAD padFile OF mainMenu ACTIVATE POPUP popFile
DEFINE POPUP popFile MARGIN RELATIVE SHADOW COLOR SCHEME 4
DEFINE BAR 1 OF popFile PROMPT "Open \<Estimate" KEY CTRL+E, "CTRL+E"
DEFINE BAR 2 OF popFile PROMPT "Ouvrir \<Purchase Order" KEY CTRL+O, "CTRL+O"
DEFINE BAR 3 OF popFile PROMPT "Ouvrir \<Production Order" KEY CTRL+P, "CTRL+P"
ON SELECTION BAR 1 OF popFile ;
    _Screen.ActiveForm.openEstimate
ON SELECTION BAR 2 OF popFile ;
    _Screen.ActiveForm.openPurchOrd
ON SELECTION BAR 3 OF popFile ;
    _Screen.ActiveForm.openProdOrd
ACTIVATE MENU mainMenu nowait
 
Paco,

dan said:
Menu code exists "outside" the form object so you can't use "thisform"

Dan said this 25 minutes before your post

Paco said:
i get the error "Thisform can only be used within a method"

So in the end you start a top level form and a menu, that you want to make calls into this top level form from the menu, right?

And this top level form is your main form and it will only be started once, right?

But you also start new forms, don't you?

Then _screen.Activeform will not always adress the main top level form. If you want (some or most of your) menu to control the top level form, then rather think about a way to always adress that form, eg like this:

In your top level form init() add this line:
Code:
* top level form init
* ...
_screen.AddProperty("oMainForm",This)
* ...

Then change all your _screen.ActiveForm references in the menu items, that should always address the mainform to _screen.oMainform

And going back to your initial question, you then can also do things like:
Code:
_screen.oMainform.myProperty = "TEST"

_screen.activeform must be used cautious for something, any form of your app will support, only, and also if closing your main form does not close the app, _screen.Activeform can get NULL, which makes code using it fail. That may not be the case, but still _screen.activeform will address the active form, no matter what it is, that's not what you want.

In regard of the other case, where you start a form and then set it's properties (or actually tried it the other way around), the normal way to go about this, is to add an LPARAMETERS to the form init and to call the form with parameters passed to the init, for example:

Code:
* Form.Init() code:
LPARAMETERS tcCaption

This.Caption = EVL(tcCaption,"Default Caption")

* Call of the form
Do Form yourform WITH "Non Default Caption"

Bye, Olaf.
 
One other point, Paco ....

Your code includes this line:

Code:
ON KEY LABEL ESC KEYBOARD CHR(13)

You should be aware that this comand has a global scope. In other words, you will be changing the behaviour of the ESC key throughout the application. I'm not sure why you have this command in this particular place, but you need to change it back as soon as it is no longer needed.

Mike


__________________________________
Mike Lewis (Edinburgh, Scotland)

Visual FoxPro articles, tips, training, consultancy
 
@Olaf

Thanks for the tip i did not knew i could set properties to _screen. I tried it and it works #1. My application has more than one screen but except the top one the others are dialogs so i think it might have worked without setting a _screen property. The top level form also close the application completely.

@Mike

The line

Code:
ON KEY LABEL ESC KEYBOARD CHR(13)

is a remnant of the .mpr generated file... i kept it because he was here. I removed it since it is now useless. Thanks
 
but except the top one the others are dialogs so i think it might have worked without setting a _screen property.

If you want to say with "dialogs" they are modal forms like messageboxes, meaning you can not choose menu items, while they are active, only while the top level form is the active one, yes, then _screen.activeform would be sufficient in the menu.

Bye, Olaf.
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top