Session E-MENU

Menus, GENMENUX & Beyond

Andrew Ross MacNeill
Melton Technologies Inc.


Menus: A Key Component to Application Design

Since 1984, graphical interfaces have introduced developers to new terms and concepts: windows, icons, mice, toolbars, the list goes on. The graphical interface also refined a lot of steps in the application development process by introducing standard ways of presenting information. Tabbed dialogs are becoming increasingly popular as are floating toolbars. Many of these new items suggest that menus aren’t needed anymore. Many developers try to get rid of their menus by having every function in an application on a toolbar. But menus are necessary for two important reasons:

These are suggested guidelines to menu design. Let’s take a closer look at the use of these ideas in an application.

One of the biggest problems that application developers face is user-training. An application always make perfect sense to the developer who designed it; but put it in front of a new user, and the terms "confusing", "unsure" and sometimes even "stupid" starts coming into the user’s vocabulary.

Windows was supposed to change all that. By presenting a standard user interface, users would be able to learn new applications quicker. An important part of a standard interface is the menu. Think about the changes people had to make when switching from Lotus 1-2-3 to WordPerfect in DOS. The keyboard controls were different; the menus were non-existent and as a result, there are a lot of people who "know" WordPerfect but know nothing about 1-2-3, and vice-versa. Now think about the change between Word and Excel under Windows. For the most part, the applications’ interfaces are identical.

This is a big part of building applications that run under Windows. Even the most specific vertical market application should support common interface standards if it is running under Windows. This makes it easier for the end user to learn and then support the application. As users become more familiar with an environment, they tend to be more demanding about it. The less demands are met, the more hostile they can become towards a product. If a user has learned to use Windows and off the shelf Windows applications, they are likely to learn a similar looking product much faster than one that introduces a completely different look and feel.

This discussion could turn very easily into a large argument, discussing the problems with the basic Windows interface. The other point is that interfaces change over the years. Five years ago, toolbars were considered ornate; now they are necessary. With Windows 95, the approach developers take to design will change and beyond that, changes will be made once again. The important part is to present a unified, consistent and common interface to the users.

First question is "what is a complexity browser?" When introduced to an application for the first time, users take two different approaches: 1) solve the problem currently at hand or 2) see what the application can do. Users who want to solve a current problem or perform a certain task will force their way through an application but eventually, all users will want to know what the application can do. This is where menus are powerful interface tools and also suggest ways that developers can use toolbars to their best advantage. Let’s take the example of a simple invoicing and customer management system.

In our sample application, there are several things that need to be managed in the application context:

There are also a few functions that need to be managed in the overall application:

This is a basic look at the functional requirements of this application. The first 6 functions are most commonly performed by an end user. In fact, the other options (including Remove Invoices) are either functions that the application shouldn’t make too accessible to the end user or are functions that should appear to be redundant (such as Online Help and multiwindow management).

By placing these items on a menu based on how often they are intended to be used, an application accomplishes two goals:

What could be one implementation of this application menu? Not following any standards but the application’s, it might be possible to conceive of a menu that looks like this:

However, let’s keep in mind the first point which is providing the user with a common interface. The application should be easy enough that a user who knows how to use other applications should be able to learn this application without additional help. To help, think about the answers to these questions in regards to the Windows interface (hints are placed in the parentheses):

As well, if the application were to expand, the original menu approach would have to change dramatically. If the application provided the ability to have different "accounts" with different customers in each account, the approach would change slightly. Would it change if a GUI standard was followed? It might but once again, it might be easier to follow. Consider the following menu structure:

The File Menu allows users to create, open and close new accounts of information. In a single account system, these menu items are disabled and the system defaults to the current account. The File menu also contains the ability to Export Customers and Invoices, Print Invoices and other reports, configure the printer as well as exit the application.

The Edit menu allows users to use Windows clipboard functions as well as search within the application for various information.

The View menu allows users to choose the information needed: Customer, Product or Invoice.

The Options menu allows the user to set his or her own preferences.

The Tools menu gives access to User Security, other maintenance tables and System Administration functions such as Pack and Reindex.

The Window menu lets the user minimize, maximize or move windows on the screen.

The Help menu gives full access to online help as well as application information.

Where do toolbars fit in? Now the application could actually use a typical Microsoft-style toolbar for most of its functionality. So not only has the menu redesign made it easier to find information, it has also allowed the toolbar to be designed with a common interface as well.

Devise menus that change to reflect the current mode of the application

This is similar to using OLE 2.0. For example, the Options menu for Customers may include an option to "Call Customer" where the Options menu for Invoices may include an option to "Ship Invoice". These options only appear when the user is looking at the appropriate form. This is a very useful design approach to menu development. It keeps the basic menu consistent while offering lots of different options.

These guidelines aren’t the only approach to menus; however, they provide a basic solution to providing the users with an easy to use yet powerful menu interface in their application. As developers, we often find better ways of building our applications; we need to keep in mind that our users need to "find" this better way for themselves. Menus are one way to do it.


The Menu Builder

The Menu Builder in Visual FoxPro hasn’t changed that much from FoxPro 2.x. It can still be called by typing "CREATE MENU" or clicking on File - New - Menu. In fact, the only new feature on the Menu Builder itself is the ability to Negotiate where menu items appear for OLE objects. There is no component of the Visual FoxPro 3.0 Menu Builder that is OOP. Menus are broken into several different parts:

In the Menu Builder, little distinction is made between Pads and Bars. The main distinction in the Menu Builder is what happens when a menu item is selected. There are four choices:

By selecting Command, the developer supplies a single line FoxPro 0command statement to be executed when the user clicks on the menu option. An important note about Command menu options is that the Command statement is identified along with the DEFINE BAR/PAD statement.

The Pad Name / Bar # option allows developers to identify a name for a menu item. This is not very useful in the Menu Builder selection options as it prevents a menu from being used for other items. A more useful approach is to use the Pad Name / Bar # option in the Options button in the Menu Builder.

SubMenus generate popups that are called when the user selects the menu option. By creating submenus on Menu Bars, it is possible to have hierarchical menus or "menu trees" as in the Wizards menu option above.

By using procedures, the Menu Builder allows developers to write snippets of code that are then run when the user selects the menu option. The biggest problem with procedures is the way the menu builder creates the code. The procedure name is randomly defined during the Menu Generation process and is only known during that process. The code the Menu Generator then writes is a call to that random name that exists only in the MPR file.

There are some other useful features of the menu builder.

Quick Menu generates a duplicate of the Visual FoxPro menu system. This is useful to create a menu system that mirrors the FoxPro system with keyboard shortcuts and automatic behaviour.

Preview allows the developer to see how the menu will appear to the user. One problem with Preview is that it does not take into account menus that replace existing menu options.

The Options box is the small grey button beside each menu option. The options box allows developers to identify Keyboard shortcuts, messages and the Negotiate settings for the Menu pad. It also provides access to the Comment snippet.

Under the View Menu, General Options allows the developer to define Setup and Cleanup code for the menu file as well as a default Procedure statement. This statement is called whenever a user selects an item that does not have an action already defined for it.

As well, General Options allows the developer to "place" the menu in the application setting.
Option Description
Replace Replaces the existing FoxPro Menu system in its entirety
Append Adds the new menu to the existing menu system that is in place when the menu file is run
Before Allows the developer to place the menu before an existing FoxPro menu pad. This is useful if Quick Menu was used to generate menu locations for the main application menu.
After Allows the developer to place the menu after an existing menu pad.

Also under the View menu, the Menu Options allows the developer to define generic procedures that are run whenever a user selects an item within the popup or submenu that does not have an action already defined for it.

When a menu item is hit by a user, Visual FoxPro follows this chain of command:

By putting a simple "WAIT WINDOW ‘Not ready yet!’" statement in the Menu procedure code, a menu system would always do something when the user selected an option, even when no code was written for it.

Here is a quick list of major limitations of the FoxPro Menu Builder:

The big new feature in the Menu Builder is the ability for menu pads to negotiate their position with OLE Objects. With OLE 2.0, OLE objects take over an application’s menu system and their menus become the standard menu until the user exits out of the Object. Using the Negotiate feature, developers are able to identify where their menus go when the OLE Object’s menu appears. Menu Pads can either appear not at all (the default), Left, Middle or to the Right of the OLE Object’s menu.

In order to make use of the Menus created in the Menu Builder, an MPR (or Menu PRogram) must be generated. This is done by selecting Generate.

The Menu Builder itself is simply a front end that creates a DBF-style table with an MNX extension, the memo field is called MNT. The Menu Generation process takes the MNX file and reads it record by record in order to create a single program file called the MPR statement. This generation process is controlled by the program specified in the system variable _GENMENU. By default, Visual FoxPro uses a program callled "GENMENU" to accomplish this task.

What FoxPro lacks in the Menu Builder, it attempts to make up for it in the language clauses available to the developer. Here is a summary of those commands that are extended using the FoxPro Language instead of the Menu Builder. This is for information purposes only. You should always use the Menu Builder wherever possible in application development. Access to language extensions is available through GENMENUX which is discussed below.

 
Component Base Language Syntax Language Description & Extensions
Main Menu DEFINE MENU menuName Defines the name of the menu. This is never called by the Menu Builder. The menu name always defaults to _MSYSMENU. In order for any of these extensions to work, the menu name cannot be _MSYSMENU.

Menu Extensions include:

IN WINDOW - allows developer to place menu within a user defined window.

AT LINE - allows developer to place a menu at a specific line location instead of row 0.

FONT, STYLE - allows developer to specify a font, size and style for the entire menu. This allows the creation of WYSYWIG menus.

COLOR SCHEME - allows developer to specify a color pair or color scheme for menu.

Menu Pads / Menu Bars DEFINE PAD x OF menuName PROMPT

DEFINE BAR x OF popupname PROMPT

Defines the pad prompt for a menu.

Menu Extensions include:

AT nrow, ncol - allows developer to place menu pad at a specific location

BEFORE | AFTER - allows developer to place a menu pad at a location relative to another menu pad

FONT, STYLE - see above

Menu Popups DEFINE POPUP popupName Defines the basic popup for a submenu. By defining Bars for a popup, a submenu is created.

Menu Extensions include:

FROM ... TO - allows developers to size and place popup in a specific location

IN WINDOW | IN SCREEN - allows developers to place popup within a particular window or screen

FONT | STYLE - as above

MOVER - places a Mover button in popup allowing users to move menu items around the popup

MULTISELECT - by default, popups may have a single item selected. MULTISELECT allows users to select more than one item on a popup at once.

PROMPT FIELD | STRUCTURE- allows developers to display the contents of a table instead of identifying BARs. Useful for dynamic menus.

PROMPT FILES - allows developers to display files meeting a particular structure

TITLE - allows developers to identify a title for the popup

 

 


GENMENUX 3.0

For full information on GENMENUX, please refer to the full GENMENUX documentation.

GENMENUX is an extension for the FoxPro Menu Generation process. As long as FoxPro uses a GENMENU style program to create menus, GENMENUX may be used to provide better features and access to the Menu Builder.


Beyond Menu Builder

The biggest problems with the Menu Builder is that unlike the Visual FoxPro Form Designer, it requires generation of an MPR file and is not object-oriented. Are there other solutions? None authorized by Microsoft and based on public discussion, the Menu Builder’s days as a Generated program are numbered.

When will that happen? It’s anyone’s guess, however until that time, there are ways of extending the Menu Builder. GENMENUX allows programs to be written to extend the generation process. One of such programs converts the MNX file into a Visual Class Library that can be called to control menus as if they were object-oriented. Unfortunately, it still requires the Menu Generation process.

Another solution is in the works that directly reads the MNX file and treats it like an object itself. However, the problem will all of these approaches is that they are temporary. The real solution requires Microsoft to build a truly object-oriented menu designer.

 



Session E-MENU

Menus, GENMENUX & Beyond

(Attached)

Andrew Ross MacNeill
Melton Technologies Inc.


GENMENUX - A Menu Extender

GENMENUX is based on the concept behind GENSCRNX by Ken Levy of JPL and the initial program by Steven Black. The idea behind the "X" series of generators is that there are times when FoxPro does not provide everything required in the Power Tools. The "X" series provides additional functionality that can add incredible power to these tools.

GENMENUX was originally conceived by Steven Black to provide automatic menu translation for his INTL GENSCRNX Driver, which creates truly international-ready applications. Additional modifications were made to make GENMENUX a more powerful and generic tool.

GENMENUX 3.0 supports both Visual FoxPro 3.0 and FoxPro 2.x for all platforms.

GENSCRNX was designed by Ken Levy and provides major extensions to the FoxPro screen builder in the same way that GENMENUX extends the menu builder.

Since the most common complaint I've heard about the Menu Builder is that it forces the developer to use FoxPro's format of menus : shadows, placement, etc. GENMENUX attempts to provide power back into the developer's hands.

It enhances the FoxPro Menu Builder with the following features :

Technically, these generators copy a screen or menu and make modifications to the copy prior to building. This way, the original screen remains the same. For more information on GENSCRNX and the entire concept behind the "X" series, see the documentation for GENSCRNX.

As with GENSCRNX, GENMENUX has been placed in the Public Domain.

GENMENUX directives may be called in four different locations :

The CONFIG.FP is the startup configuration file that FoxPro uses. In order to use GENMENUX at all, you must specify it as the replacement for GENMENU with the following line :

If you have added FoxPro into your DOS path, you should put the entire path into the GENMENUX line.

Any Setup directives may be called from either the Setup snippet or the Menu Procedure snippet. You can access the Menu Procedure snippet easier than the Setup snippet as it is immediately visible when choosing Menu options from the Menu pad.

The comment snippet is available by selecting Options for any particular menu.

When you create a menu using the Menu Builder, FoxPro carefully constructs the MNX file in a particular manner. When adding and removing menu items directly into the MNX file, it is crucial that the order and content of the MNX file is maintained. For example, FoxPro maintains the number of menu items for each menu pad and bar in the MNX file. If you remove one of the items without updating the number of items, GENMENU builds an invalid MPR file.

To reduce this from happening, GENMENUX reorders the menu after processing the majority of its directives and running MNXDRV1 and MNXDRV2. This allows users to create their own drivers that add and remove menu pads and bars without worrying about messing up the order of the MNX file. If you design such a driver, it is important that you call it in either MNXDRV1 or MNXDRV2. If you remove menu pads in MNXDRV3 or later, you will corrupt the MNX file and the MPR file will be unusable.

With the release of version 1.1, GENMENUX offers the concept of Menu Templates or Libraries, similar to the screen libraries offered with GENSCRNX.

Notes for FoxPro Windows

FoxPro for Windows handles Menus slightly differently than DOS in order to conform to the Windows standard. One of the differences is that the main system menu _MSYSMENU is not allowed to be moved from the top of the desktop. To overcome this, add the directive *:MENUNAME to your menu and rename it to something other than _MSYSMENU. This will result in a Menu that will use the default FoxPro for Windows font which is FoxFont Size 10. If you want to have a more "Windows" like menu, DEFINE your window using the FONT clause of "MS Sans Serif",10.

Directives that are new in GENMENUX 3.0 are highlighted in italics.

 
CONFIG.FP Directives - all CONFIG.FP directives are preceded with a _
_BASEHDR Identifies standard program to hold all standard Setup directives.
AUTOACT Automatically Activates the menu after creating it.
AUTOHOT Automatically adds Hot keys to top menu bar without labels. (ALT+ only)
AUTOPOS Allows the developer to place the menu on a line when it is being compiled.
AUTORUN Automatically runs the menu upon completion.
FOUNDATION Automatically creates a FOUNDATION READ at the bottom of the menu file.
FOXMNX Defines the Menu Template File.
GENMENUX Runs driver specified instead of standard GENMENU.
HIDE Hides the Menu while the MPR file is being run so menu pads won't distract the user.
MNXDRV1-5 Identifies Driver x for the MNX file
MPRDRV1-2 Identifies MPR drive for the MPR object file
NOXTHERM Removes the GENMENUX Extended Thermometer in favour of the traditional FoxPro.
REFPRG Identifies Refresh Program that GENMENUX will create to help in the refreshing of conditional CASE and ARRAY menus.
SYSPOP Wraps all procedures with PUSH MENU _MSYSMENU ,POP MENU _MSYSMENU statements to preserve menu settings before a procedure is called.
Setup/Menu Procedure Directives - all setup directives are preceded with a *:
{{}} Identical functionality to {{}} in GENSCRNX.
AUTOACT Automatically Activates the menu after creating it.
AUTOHOT Automatically adds Hot keys to top menu bar without labels. (ALT+ only)
AUTOPOS Allows the developer to place the menu on a line when it is being compiled.
AUTORUN Automatically runs the menu upon completion.
AUTOVERSION Directive that makes the first menu bar into an incrementing number and converts the MPR file into a simple PRG that runs whatever code is in the procedure of the first menu bar.
BARHOT Automatically adds CTRL hot keys for a menu item or submenu.
DEFCOMMAND_ALWAYS Specifies a command statement to be run whenever the menu bar doesn’t have a command to be filled in. This replaces all existing command statements. Only used for Menu Bars calling Commands.
DEFCOMMAND_INCLUDE Specifies a command statement to be run whenever the menu bar doesn’t have a command to be filled in. This replaces only empty command statements. Only used for Menu Bars calling Commands.
DEFLIB Defines the Default Library to be used when defining menu template objects.
FOUNDATION Automatically creates a FOUNDATION READ at the bottom of the menu file.
FOXMNX Defines the Menu Template File.
HIDE Hides the Menu while the MPR file is being run so menu pads won't distract the user.
INCLIB Defines the Default Library to be used when retrieving menu template objects.
INSSCX Inserts a DO .MPR call within a screen file. Also allows you to call the menu from within a MODAL screen and preserve the original menu settings.
LINE Places the menu at line specified. This should be a numeric value. Be warned under Windows!
LOCATION Allows you to set the location of the menu in relation to the current menu (REPLACE, APPEND, BEFORE or AFTER) instead of having to identify it under Menu Options.
MENUCOLOR Adds the COLOR clause setting to the DEFINE MENU statement if one is present in the MPR file.
MENUNAME Renames the default _MSYSMENU menu name in the MPR file to whatever is specified. This does not have to be in quotes. If it is, the quotes are stripped from the word.
MNXDRV0-5 Identifies Driver x for the MNX file
MPRDRV1-2 Identifies MPR drive for the MPR object file
NOACT Removes the statement ACTIVATE MENU _MSYSMENU from the MPR file.
NOAUTO Removes the statement SET SYSMENU AUTOMATIC from the MPR file.
NOBAR Removes the BAR statement. Usually only required if renaming menu. Be warned under Windows!
NOGEN Does not generate the MPR file
NOLOC Removes the LOCFILE statement from the MPR file
NOMARGIN Removes the MARGIN clause from the MPR file.
NOSHADOW Removes the SHADOW clause from the MPR file.
NOXGEN Does not process any GENMENUX directives.
NOXTHERM Removes the GENMENUX Extended Thermometer in favour of the traditional FoxPro.
PADCOLOR Changes the Default Menu Pad color from color Scheme 4 to whatever number is specified. No quotes please!
POPCOLOR Changes the Default Menu Popup color from color Scheme 4 to whatever number is specified. No quotes please!
REFPRG Identifies Refresh Program that GENMENUX will create to help in the refreshing of conditional CASE and ARRAY menus.
SELECTBAR Changes the ON BAR statements to ON SELECTION BAR.
SELECTPAD Changes the ON PAD statements to ON SELECTION PAD.
SKIP_AUTO Automatically calls the SKIP_REDIRECT procedure if used
SKIP_REDIRECT Places all SET SKIP statements into a separate procedure in the MPR file making it much faster to regenerate the menu.
SYSDEFAULT Makes the Menu become the FoxPro default by adding the line SET SYSMENU NOSAVE to the bottom of the MPR file.
SYSPOP Wraps all procedures with PUSH MENU _MSYSMENU ,POP MENU _MSYSMENU statements to preserve menu settings before a procedure is called.
VERTICAL Makes a menu orientation vertical instead of horizontal starting at a particular location.
WINDOW Allows you to place a menu within a window and define the window within the MPR with specific window definition clauses.
Comment Directives - all Comment directives are preceded with a *:
{{}} Identical functionality to {{}} in GENSCRNX.
ARRAY Makes a menu popup definable by an array instead of within the MPR file. Good for dynamic menus.
BARHOT Automatically adds CTRL hot keys for a menu item or submenu.
CASE Adds or removes a menu bar when a general condition is not met.
CLAUSE <cExpr> Allows user to identify any additional clauses after the DEFINE statement
COLOR Allows you to designate a Color Pair setting for a particular menu item. Under Windows and Macintosh, allows you to identify color by name.
COLORSET Allows a specific color scheme setting for a particular menu item.
DEFOBJ Defines the current menu pad/procedure as a menu object in the menu template file.
DEFPOPIF Makes the definition of a menu popup conditional if the menu popup already exists. This has no effect on the options of the popup but will speed up the running of the MPR file.
DELETE Removes menu pad prior to calling GENMENU
DELOBJ Removes menu pad prior to calling GENMENU but AFTER initial GENMENUX directives has processed.
FONT Places a FONT, STYLE setting beside the DEFINE xx statement in the MPR file
GENIF Removes a menu pad or bar from the MNX file during compilation if condition is not met.
IF RELEASES a menu PAD or BAR if condition is not met
IGNORE Tells GENMENUX to ignore the menu or the pad for GENMENUX processing.
INSOBJ Inserts a menu object from a menu template file.
MESSAGE Adds a message clause to the menu definition. This replaces the FPW's message clause. The message must be enclosed in quotes unless it is a variable.
PADNAME Identifies a particular name to a menu pad without having to go into Menu Options.
PADPOS Defines the menu pad at a particular row and column.
POPCOMMAND Adds the line ON SELECTION POPUP for each popup using POPFILES or POPFIELD, the expression must be a valid FoxPro command. Quotes ARE NOT STRIPPED from the expression.
POPFIELD Allows for a popup of fields matching the file spec matching the expression. Quotes are not needed and if used, will return the text instead of the field.
POPFILES Allows for a popup of files matching the file spec matching the expression. Quotes are ignored in the expression as per standard FoxPro behaviour
POPNAME Identifies a particular name to a menu popup without having to go into Menu Options.
POPPOS Defines the menu popup at a particular row and column.
POPPRECOMMAND Identifies a particular command to be run before a popup is defined. For use with the POPFIELD and POPFILES directives only.
POPTITLE Identifies a particular title for a menu popup.
SYSPOP Wraps all procedures with PUSH MENU _MSYSMENU ,POP MENU _MSYSMENU statements to preserve menu settings before a procedure is called.
TRNTXT Translates Text within a procedure file.