Of the four types of menu items, probably the easiest to use is the type that transmits a string of keyboard characters when selected. These can be set up to transmit the same characters that a real user would type on the keyboard, and thus the program needs no special code to detect and process the selections (other than adding them to the menu in the first place and deleting them later.) This is possible even though a single Windows menu option in this case will span two separate menu programs. For example, to select the first choice on the top level menu and the third choice on the second level menu, we could just make the keyboard string be "1"+chr(13)+"3"+chr(13). The first part of the string would be responded to by the top level menu program, and the second part would still be in the keyboard buffer, and thus responded to by the second level menu program.
One complication to be overcome, though, is how to input the chr(13) (aka carriage return) control character into the MDF. Fortunately, there are two ways to do this. One is to use the Control-G lead-in, which tells the A-Shell/VUE editor to insert the next character into the file as-is, rather than treating it as a command. So the sequence Control-G Control-M would insert the carriage return character (i.e. chr(13) or Control-M) into the file, displaying it as a dim M. The only problem with this approach is that may create confusion when printing or typing the MDF on the screen or editing it with another editor. To avoid those problems, as of Build 828.2, you can also use the special notation of ^X to indicate Control-X (where X can be any character from A-Z, plus [, ], \, ^, and _.) For example, consider the following line:
&G/L,"Account Maintenance",KBD,"1^M3^M"
This would create a menu item that transmitted the keyboard characters "1" followed by chr(13) (aka Control-M) followed by "3" followed by another Control-M.
The other complication with this approach is to make sure you disable or remove the menu items as soon as we change to a context where there are no longer appropriate. Fortunately again, this is reasonably simply in a menu program. All we have to do is insert a call to disable or delete the menus immediately prior to chaining from or exiting the menu.
To complete our example, here is the ashelp.mdf we’ll use:
;Menu Definition File for GL, AR, AP, PR
;G/L is the first item on the main menu;
; its selections can be reached by entering 1 <CR>
; (to get to the GLMENU program), then the appropriate
; # followed by another CR…
TOP,"&G/L",SUB
&G/L,"Account Maintenance", KBD,"1^M1^M"
&G/L,"Period Maintenance",KBD,"1^M2^M"
&G/L,"Transaction Entry", KBD,"1^M3^M"
&G/L,"Financial Statements", KBD,"1^M4^M"
;A/R is the second item on the main menu
TOP,"&A/R",SUB
&A/R,"Customer Maintenance", KBD,"2^M1^M"
&A/R,"Sales Transactions", KBD,"2^M2^M"
&A/R,"Cash Receipts",CMD, KBD,"2^M3^M"
&A/R,"A/R Reports",CMD, KBD,"2^M4^M"
;A/P is the third item on the main menu
TOP,"&A/P",SUB
&A/R,"Vendor Maintenance", KBD,"3^M1^M"
&A/R,"Expense Acct Maintenance", KBD,"3^M2^M"
&A/R,"Voucher Entry", KBD,"3^M3^M"
&A/R,"Payment Processing", KBD,"3^M4^M"
&A/R,"A/P Reports", KBD,"3^M5^M"
;We'll also add a separator bar and then our application's
; documentation file to the Help menu
HELP,"h1",SEP
HELP,"Application Documentation",REG,"c:\vm\miame\doc\app.pdf"
Note that the "h1" in the first HELP menu line above doesn’t display but is needed in order to have a unique identifier for the separator bar, so that it can be deleted later. Also note that the second HELP menu line above use the menu type "REG" rather than "KBD". The "REG" type uses the Windows Registry to open the specified document with the application that has been previously registered to understand that type (Acrobat in the case of PDF.)
Here’s an example of the code to reference the above MDF, adding it to the menu bar at the start of the main menu program and removing it before ending or chaining to another program:
START:
OPCODE = 1 : STATE = 0 ! (add, enable)
call DO'WIN'MENU
DO'MAIN'MENU:
! Display and process main menu…
print tab(10,10);"1. General Ledger"
print tab(12,10);"2. Accounts Receivable"
print tab(14,10);"3. Accounts Payable"
print tab(18,10);"Enter Selection:"
input "",SELECT
if (SELECT < 1 or SELECT > 3) goto EXIT'PROGRAM
CHAIN'TO'SELECTION:
OPCODE = 3 ! (delete)
call DO'WIN'MENU
chain PROGRAM$(SELECT)
EXIT'PROGRAM:
OPCODE = 3 ! (delete)
call DO'WIN'MENU
end
! add/delete/change Windows menu items
! Inputs: OPCODE (1=add, 2=change, 3=delete); STATE (0=enable, 1=disable)
DO'WIN'MENU:
! If MAIN.MDF exists, do it
LOOKUP "MAIN.MDF",X
if X # 0 then xcall MIAMEX, MX_WINMNU, OPCODE, "MAIN.MDF", STATE, STATUS
return
One "error" in the above program is that it removes the HELP menu selection (which presumably ought to be available from anywhere in the application) along with all of the rest of the menus when it chains out of the main menu. To treat one set of menu items (in this case the HELP menu) differently from another set, you can use multiple MDFs. In this case, it would have made sense to have one MDF for the G/L, A/R and A/P menus, and one for the HELP menu. The HELP menu could then have been left in place while the others were deleted. We could also have just handled the HELP menu addition with the "traditional" form of MX_WINMNU, since there is little advantage to the MDF technique for adding just one item.
When using multiple sets of menu items, the main limitation is that they be structurally independent from each other so that they can be added and deleted independently from each other. The simplest way to ensure this is to not mix groups of independent menu items on the same submenu.