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!

ACTIONS ON AUTO GENERATED MENU OF VFP

Status
Not open for further replies.

dexterdg

Programmer
Jan 6, 2013
85
PH
i have an auto generated menu for my mdiForm form the menu designer and im having problems in puting actions actions to the selected menu. what i did is appended codes to the generated menu.mpr

*!* code i appended
ON SELECTION BAR 1 OF file mdiForm.fmethod1() --> not working [Transaction Log]
ON SELECTION BAR 2 OF file mdiForm.fmethod2() --> not working [Exit]
ON SELECTION BAR 1 OF manage DO FORM formManage1.scx --> working [Manage Employee]
ON SELECTION BAR 2 OF manage DO FORM formManage2.scx --> working [Manange Dependents]
ON SELECTION BAR 3 OF manage DO FORM formManage3.scx --> working [Manage Users]
ON SELECTION BAR 1 OF hep mdiForm.hmethod1() --> not working [About]
ON SELECTION BAR 2 OF help mdiForm.hmethod2() --> not working [Manual]

is there a better or easier way to put actions to these? or is there a correct way of implementing methods to these?

thanks for the help! :)

Dexter
 
Dexter, my guess is that mdiForm is not in scope at the point that the user selectes the relevant menu command.

You'll remember from your earlier thread that mdiForm is a variable that contains an object reference to a form. If the variable has gone out of scope when the user makes the menu selection, VFP has no way of knowing which form you are refering to. That explains the problem you are seeing.

We explained how to deal with this in the other thread (thread184-1701409).

Another solution would be to ensure that menu commands never call methods of a form. Instead, have them call functions in a procedure file (the kind you create with SET PROCEDURE). However, that might mean a certain amount of re-factoring of your code, which might not be worth the trouble at this stage.

Mike






__________________________________
Mike Lewis (Edinburgh, Scotland)

Visual FoxPro articles, tips, training, consultancy
 
thank you for the option sir mikelewis! worth trying the SET PROCEDURE. if the reply on the previous thread wont work. because at first i tried applying the poMDIForm = .NULL. ; DO FORM mdiForm NAME poMDIFORM, yes it redirects but because of the slowness of my unit i can see that it vanishes mdiForm which makes DO FORM not usefull. it would be nice if i can use poMDIForm.[method] if it will work.

thanks
Dexter
 
poMDIForm = .NULL.
DO FORM mdiform NAME poMDIForm LINKED

This code is NOT meant to be in a menu item, this code from your other thread is meant to be within the starting PRG, and should execute before you even start the menu, to generate the variable poMDIForm, initialise it with .NULL. and then set it to the form reference by the NAME clause auf the DO FORM command.

Your MDI Form shoiuld be the main application form always present when the application runs.

If that doesn't work out, try PUBLIC poMDIFORM instead of poMDIForm = .NULL., I actually haven't tried if a private variable will be accessible in a menu, but a PUBLIC one surely will be.

Bye, Olaf.
 
_screen.ActiveForm is an option, of course. Can also be null, or the wrong form, if the MDI main form is creating stellite/popup forms, which isn't unusual for an MDI application.

Another useful thing: Using the menu designer, change a menu item from Command to Procedure and you don't need to put things into a single line of code, then things are much easier to cope with in general. No reason to limit yourself to a single line of code.

Bye, Olaf.
 
wow! i didnt know that. must explore more on vfp environment. menu to a procedure. btw poMDIForm.[methodname] works fine in accordance to my previous thread. thanks sir olaf!

Dexter
 
*!* code i appended
ON SELECTION BAR 1 OF file mdiForm.fmethod1() --> not working [Transaction Log]
ON SELECTION BAR 2 OF file mdiForm.fmethod2() --> not working [Exit]
ON SELECTION BAR 1 OF manage DO FORM formManage1.scx --> working [Manage Employee]
ON SELECTION BAR 2 OF manage DO FORM formManage2.scx --> working [Manange Dependents]
ON SELECTION BAR 3 OF manage DO FORM formManage3.scx --> working [Manage Users]
ON SELECTION BAR 1 OF hep mdiForm.hmethod1() --> not working [About]
ON SELECTION BAR 2 OF help mdiForm.hmethod2() --> not working [Manual]

Just as a final recap:
You don't need to add code to generated menu mpr programs, as you can set a menu item from Bar# to Command or Procedure and can type in a single command or a whole procedure to execute, when a menu item is choosen.

Also for the aimed tasks of the menu, I mostly wouldn't put them as methods of your main form:
Exit: CLEAR EVENTS or QUIT is all that's needed there, no need to run a form method
About: Should rather start a new from than calling mdiForm.hmethod1()
Manual: Should rather call HELP "Topic" or HELP ID HelpContextID. For that you have to create a CHM help file yourapp.chm and in the starting routein SET HELP TO yourapp.chm

This way, only the [Transaction Log] thing remains as a call into your form, but why not make that a seperate form?

Bye, Olaf.
 
Tamar said:
Try using _SCREEN.ActiveForm.Mymethod() as the action.

The problem with using _SCREEN.ActiveForm is that it relies on the relevant form being active at the time the menu command is executed. Since the menu system lives outside the forms, there's no way of guaranteeing that. In fact, it's possible to execute a menu command when no form is active, in which case you would get a "not an object" error.

The more I read this thread, the more I am convinced that the ideal solution is not to use a menu command to call a method of a form (unless the menu is actually part of the form, perhaps, but that's not the case here). I would suggest that a menu command should do one of the following, and nothing else:

- Call a built-in menu procedure, such as Cut or Copy.

- Launch a form.

- Call a procedure or function in a PRG.

- Call a procedure within the generated MPR file; this would be a last resort, because it involves firing up the menu designer, modifying and saving the code, and remembering to re-generate the menu, every time you want to change the procedure in question.

Mike

__________________________________
Mike Lewis (Edinburgh, Scotland)

Visual FoxPro articles, tips, training, consultancy
 
Hell Mike,

that summarizes it very good. Also the recommendation to not call into form methods is a good principle. But I also can understand Dexter, because the situation is indeed the menu is integrated in that top level form (visually), because Dexter posted code in thread184-1701409:

*!*---[[mdiForm.scx]] object: form Procedure: Init
WITH THISFORM
DO menu.mpr WITH THIS, .t.
ENDWIH

That means the menu code is called with the form (THIS) as first parameter, which can be done, if you check the "Top Level Form" option. That results in the menu being put into the form header (sidenote to Dexter: the WITH ENDWITH lines in this case are useless, you don't make use of the WITH object reference at all).

Still as you said, Mike, the menu is a seperate thing. When menu code executes, it executes outside of the form scope and neither the form name nor THISFORM can be used to address the form, _screen.Activeform has the problems you describe, if another form is active, and it's therefore better to not call into form methods but rather PRGs or procedures you make known by SET PROCEDURE. If you like programming OOP, then you can also call methods of an application object, which would be created at startup, existing all the time the application runs. You just need anything reliable existing, if you want to call it in a menu item, as a menu item can be executed at any time, and of course you can also write code.

Unlike Mike I don't see the menu procedures as a ralst resort. Of course the procedures should nevertheless not be lengthy, the procedure editing is easier in an a seperate PRG, where you can edit all procedures or functions at once and can define help functions etc.

You can of course also see the form object as an application object, if the form is open all the time, still it's not necessarily active all the time, which is why a variable poMDIForm works better than _Screen.Activeform, as the variable stays the same form reference throughout the form existance, while _screen.activeform can vary, depening on - well - the active form.

So, Dexter, it's up to you to decide, what you can best live with, _screen.activeform, a variable poMDIForm holding a form reference or an application object, into which you transfer some of the code you now have in the form.

Unfortunately the menu system of foxpro has never been updated to an object oriented way includable as child object of a form. Even though the menu started the way you do is visually inside the form, it's a seperate thingy. Even the OOP Menu Project of VFPX is just using the menu commands of foxpro and integrates a menu into a top level form the same way as the generated menu code of the native menu designer does.

Bye, Olaf.
 
I didn't test yet, but to defend Tamar's position: As the menu actually is defined in the form init this way, choosing a menu item may always activate the form it's "living in", at least if you click into the menu that should also cause the form to activate. I am just not so sure about activating menu items via Hotkeys.

Bye, Olaf.
 
>You just need anything reliable existing, if you want to call it in a menu item, as a menu item can be executed at
>any time, and of course you can also write code.
Code here means commands or procedures you define within the menu designer, that is you may also transfer your form methods into menu procedures.

>ralst resort
last resort

Bye, Olaf.
 
Olaf, I hadn't taken in that it was a menu defined within a top-level form. In that case, using _SCREEN.ActiveForm might not be so bad.

It would be interesting to know whether making a menu selection has the effect of activating the form. I'll try it if I get a moment.

A similar situation would be with a context menu. That too would be quite closely bound to the form. It's almost certain that right-clicking in a control (to bring up the menu) would also have the effect of activating the form, so I guess _SCREEN.ActiveForm would be fine in that case.

I know you can't reference THISFORM from a context menu. What I've always done is to copy THISFORM to a private variable before issuing the ON SELECT BARs, and then reference that private variable in the command. That always works.

Mike

__________________________________
Mike Lewis (Edinburgh, Scotland)

Visual FoxPro articles, tips, training, consultancy
 
The thing about THISFORM was rather addressed at Dexter, but the idea of setting poMDIForm = THISFORM is not differing much from what DO FORM .. NAME poMDIForm does.

Pro: You can do it with all kinds of classes, not just with forms.

Con: The scope of a private variable you declare within the Init (and not before DO FORM) will end after the init, that makes me wonder how ON SELECTION BAR would then continue working, after the variable scope has ended.

So this rather would need the same two steps: 1. Declaring the private variable before creating the form and 2. Setting the private variable to THISFORM in form init.

Bye, Olaf.
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top