Paradox Community
Search:

 Welcome |  What is Paradox |  Paradox Folk |  Paradox Solutions |
 Interactive Paradox |  Paradox Programming |  Internet/Intranet Development |
 Support Options |  Classified Ads |  Wish List |  Submissions 


Paradox Programming Articles  |  Beyond Help Articles  |  Tips & Tricks Articles  


Implementing a Table Based Menu System
© 2001 Carolyn Wendover

Code to Create the Menu

That concludes the section on how to setup the menu table. Now we need to look at the methods used to convert the information in the table into menus. The details of how the menus are built is not included here. Mr. Chalnick's original articles discussed this in great detail and much better than I could paraphrase. His menu library is also well documented and so a deeper understanding of the process is left to the reader to discover by looking at the menu code or finding the original articles <g>. I do recommend it though as a way to get insight into some novel uses of dynamic arrays.

Instead I will focus on the methods needed and where you need to place them within your form. The menu library contains all the code needed to read the menu tables and build the appropriate menus. You only need to call these methods at the appropriate places from within your form.

You need to modify the Uses and Var methods at the form level. The Uses method needs to have two methods defined as follows:
Uses ObjectPAL
; Menu Library
lBuildMenu(var tcMenu TCursor, aUserSecurity String, exclude String) Logical
HandleMenu(iChoice SmallInt)
EndUses
lBuildMenu creates and displays the menu. You pass it the pointer to the menu table, your user's Security code, and the Exclude string. You may pass blank strings for either or both of the Security and Exclude values. HandleMenu is called whenever the user selects a menu option.

The Var section needs to include definitions for the menu library and menu table:
libUtil     Library
tcMenu      Tcursor
The other method I use at the form level is a custom method called okToLeave. It is called by the HandleMenu method if it appears that the selected menu choice will cause the application to move to another screen. The purpose of this method is to perform any cleanup needed before performing that move. I generally use this to verify data, post any changes, and record the edit mode. If everything seems OK then I return "True" from this method and the HandleMenu routine processes the user's choice. If there is a reason to prevent moving from the current screen, this routine returns "False" and the menu choice is not processed. If you do not need to do any checking prior to leaving a form, simply create this as a method that always returns "True".
method okToLeave() Logical
  return True
endMethod
At some point you need to open the menu library and menu table. I generally do this in the form's Open method.
method open(var eventInfo Event)
if eventInfo.isPreFilter() then
  ;// This code executes for each object on the form
else
  ;// This code executes only for the form
  if not libUtil.open("MENU") then
    errorShow("System Error", "Cannot open utility library.")
    return
  endIf
  if not tcMenu.open(":WORK:MENUDEMO") then
    errorShow("System Error", "Cannot open menudemo table.")
    return
  endIf
endIf
endMethod
The last form level method you need to modify is the menuAction event.
method menuAction(var eventInfo MenuEvent)
var
  constString String
  iId         Smallint
  siEvID      SmallInt
endVar
if eventInfo.isPreFilter() then
  ; Make sure that the selected item is one of
  ; the system menu items.  If it isn't, then
  ; we'll just let Paradox process it.
  iId = eventinfo.id()
  if iId > UserMenu and iId <= UserMenuMax then
    libUtil.HandleMenu(iId)
  else
    if not constantValueToName("MenuCommands", iId, constString) then
      ;probably selecting a Window selection

      ;okToLeave does cleanup before leaving screen.
      ;These three lines are optional if you
      ;do not need to do final checking.
      if not okToLeave() then
        eventInfo.setErrorCode(1)
      endIf
    else
      doDefault
    endIf
  endIf
else
  ; this next section is optional if you do
  ; not need to catch them leaving the form
  if eventInfo.id() = MenuControlClose then
    if not okToLeave() then
      eventInfo.setErrorCode(1)
      ;do not let them close
    endIf
  endIf
endIf
endMethod
This method also makes use of the okToLeave method. When a menu selection is made that results in opening a form the HandleMenu method calls okToLeave to cleanup before leaving the current screen. However, if you have implemented a "Window" menu option and the user chooses to move to an open window using this option, the system generated menu action ID will not match one of your specified tags and it will not match the standard menuCommand IDs. Therefore, we need to call okToLeave from here because we will not call HandleMenu. We also call it if the user closes this form. If you do not feel that you need to perform any special actions before leaving a form you can eliminate the use of the okToLeave method altogether.

The last piece of the puzzle is to call the method that actually builds the menu. This is performed in the page setFocus method.
method setFocus(var eventInfo Event)
  libUtil.lBuildMenu(tcMenu,stSecurity,stExclude)
endMethod
If you plan to implement the idea of different access levels for different users, then before calling the lBuildMenu method you need to determine the access level for the current user and assign that string to the stSecurity string variable. If you want to gray out certain options, assign that code to the stExclude string or pass a blank string to the method.


Demo

Associated with this article is a demo. It includes the menu library, two sample forms, two sample reports, menu and report menu tables, and a data table. I have tried to include examples of the various options discussed, hopefully making it easy and intuitive for you to implement this approach in your own applications. I know it has made things much easier for me to implement tailored menus and it is just one more building block I use to quickly put together professional applications.


Description of Demo Items

Type of item Name Purpose
Table Demo.db One of the demo forms is setup for data entry. This table contains the fields displayed on this form.
Table MenuDemo.db Table containing menu entries displayed for Forms.
Table RptDemo.db Table containing menu entries displayed for viewed Reports.
Form Form2 Second form, used to demonstrate opening a second form via the menu options. Also contains a button demonstrating calling the report menu building routine directly.
Form MenuDemo Main demo form
Report Report1 Demo of a 2 page landscape report.
Report Report2 Demo of a portrait report
Report Report3 Just one more report used to demo report capabilities
Lib DemoLib Used to demonstrate calling a library routine via the menu handling routine.
Lib Menu The main piece of the puzzle. This contains the code needed to build and handle menu options using the menu table.

Part 1 of Implementing a Table Based Menu System


Discussion of this article


 Feedback |  Paradox Day |  Who Uses Paradox |  I Use Paradox |  Downloads 


 The information provided on this Web site is not in any way sponsored or endorsed by Corel Corporation.
 Paradox is a registered trademark of Corel Corporation.


 Modified: 15 May 2003
 Terms of Use / Legal Disclaimer


 Copyright © 2001- 2003 Paradox Community. All rights reserved. 
 Company and product names are trademarks or registered trademarks of their respective companies. 
 Authors hold the copyrights to their own works. Please contact the author of any article for details.