Define a menu bar for the sample window
- Last Updated: December 29, 2023
- 7 minute read
- OpenEdge
- Version 13.0
- Documentation
To see how menus work, you can add one to the h-CustOrderWin3.w window. As it does with other objects, the AppBuilder can define most of the statements you need for your menu, using a special menu builder tool. Once you complete the menu, you can examine the syntax to confirm the exact ABL statements needed to do the job.
To define a menu bar for the sample window:
- Open h-CustOrderWin3.w and save a new version as h-CustOrderMenu.w.
- Click the Object Properties button for the window.
Remember that if the window’s frame or some other object is selected, you can use the key CTRL+Click sequence to make the window the currently selected object in the AppBuilder.
- In the Object Properties dialog box, click the
Menu Bar button
. - In the menu bar’s property sheet, call the Menu
m_CustWin.
You will add the following submenus to the menu:
- Buttons — Duplicates what the radio set and the First, Next, Prev, and Last buttons do
- Show — Duplicates the Show Warehouse Info toggle box
- Help — Displays information about the window
- Define the first of these submenus by entering a Label of
Buttons. When you tab out of that field, a default
Object name of m_Buttons is
provided for you:
You can define all the levels of submenu and menu items together in this property sheet. To indicate the hierarchy, use the << and >> buttons to indent one item relative to the one above it.
- Click the Insert button to add three new menu items in the Buttons submenu.
- To indicate that they are menu items of the Buttons submenu, click the >> button to indent the first of the items. The others indent automatically.
- Give the three items labels of No &First/Last,
No &Prev, and Allow &All,
respectively. Accept the default object names provided for you.
The ampersand in each label represents a menu mnemonic. The mnemonics let the user press a sequence of keys, each beginning with the ALT key, to select any menu item from the hierarchy. The ampersand precedes the mnemonic for each of these menu items. By default the top-level submenus are given mnemonics of their first letters, so when you are done the key sequence ALT+B, ALT+F selects the No First/Last menu item. When you press the ALT key the mnemonics are underlined to let you see what key sequences are available to you. (Showing the mnemonic underscores after the user presses ALT is the Microsoft standard and OpenEdge follows it.)
If you define a menu mnemonic key combination that duplicates an accelerator, the accelerator takes precedence.
- Click the Rule button to insert a rule following these three items.
- Click the Insert button and define an item with a label of
Navigation:
This new item is a submenu. The menu bar property sheet is flexible enough to allow you to define the entire hierarchy from the top down. It determines that this is a submenu when you add further nested items to it. If you need to, you can click the Up and Down buttons to rearrange the order of items in the menu.
- Click Insert followed by the >> button to add an item nested under Navigation, with a label of First.
- Click the Key button to enter the dialog box that lets you define an accelerator key sequence for the menu item.
- Press the up arrow on the keyboard to register that as the accelerator key for the
First button. Its keyboard name is displayed as
CURSOR-UP:
- Click OK to accept this.
- Define three more menu items at this level with labels of
Next, Prev, and
Last. Give them the accelerator values right arrow
(
CURSOR-RIGHT), left arrow (CURSOR-LEFT), and down arrow (CURSOR-DOWN), respectively:
The double indentation identifies Navigation as a new submenu with four items as menu items under it.
To provide trigger blocks to execute when these items are selected:
- From the design window, select Buttons > No First/Last, then select Window > Code Section Editor to bring up the trigger code for
m_No_FirstLast. - To duplicate the effect of the radio set button with the same label, copy its
ASSIGNstatement into the new trigger:DO: ASSIGN BtnFirst:SENSITIVE IN FRAME CustQuery = NO BtnLast:SENSITIVE IN FRAME CustQuery = NO. END. - Make one change to the statement to qualify each button with the name of the frame
it is in.
Why is this necessary here and not in the trigger block for the radio set? Both the buttons and the radio set are in the frame called CustQuery, so the AVM identifies the frame for the buttons by default. The menu, however, is not part of the frame, but rather is owned by the window. For this reason the AVM requires that you identify the frame where the buttons are located.
This is the
CHOOSEtrigger for the m_No_Prev item:DO: BtnPrev:SENSITIVE IN FRAME CustQuery = NO. END. - The next code block is the trigger for the m_Allow_All item.
So that you do not have to type IN FRAME CustQuery three
times, make it the default frame for an entire
DOblock:DO: DO WITH FRAME CustQuery: ASSIGN BtnFirst:SENSITIVE = YES BtnLast:SENSITIVE = YES BtnPrev:SENSITIVE = YES. END. END. - Define trigger actions for the four Navigation menu items.
These triggers duplicate the actions of the
CHOOSEtriggers for the four buttons with the same labels. Often you will want some of your menu items to duplicate the action of toolbar buttons. In general, it is considered appropriate user interface design to provide a menu item for every toolbar button, such that the toolbar buttons duplicate the most frequently used menu items. One way to do this without duplicating code is to apply theCHOOSEevent to the button from the menu item, as in this trigger block for them_Firstmenu item:DO: APPLY "CHOOSE" TO btnFirst IN FRAME CustQuery. END. - Make similar changes to the
m_Prev,m_Nextandm_Lasttriggers to enable their actions for the same menu items as well. - Run the window and try out all the buttons and accelerators,
including the nested items under the Navigation submenu:
To complete your menu bar:
- Go back into its property sheet. You can do this by selecting any item in the menu in the design window and clicking the Object Properties button.
- Add a top-level submenu called Show, with a menu item of Warehouse Info. Check on the Toggle-box toggle box to make this a menu item that represents a logical value.
- Add a final top-level submenu called Help, with a menu item
called Help About. The property sheet should look like this
when you finish:
The Warehouse Info item is selected to show that the toggle box is checked
- Define a trigger for the Warehouse Info item:
DO: DO WITH FRAME CustQuery: IF SELF:CHECKED THEN ASSIGN lShowWarehouse:SCREEN-VALUE = "YES" cWorstWH:HIDDEN = NO cBestWH:HIDDEN = NO. ELSE ASSIGN lShowWarehouse:SCREEN-VALUE = "NO" cWorstWH:HIDDEN = YES cBestWH:HIDDEN = YES. END. END.Because it is a toggle box item, it has a
VALUE-CHANGEDtrigger rather than aCHOOSEtrigger.This duplicates the code for the Warehouse Info toggle box in the window, but also sets the screen value of that toggle so that the two are kept in sync. Remember that the
SELFkeyword within a trigger block always refers to the object handle that invoked the trigger. TheCHECKEDattribute tells you whether the menu item is currently checked or not. Each time you select this menu item, the check box alternately appears and disappears, and the value ofCHECKEDreverses between true and false.
As with earlier triggers, you have to enclose all of this in a DO WITH FRAME
CustQuery block to identify all these objects.