Menu Management
Volume Number: 9
Issue Number: 2
Column Tag: Getting Started
On the Menu for TodayÄ 
How does the Macintosh Menu Manager work?
By Dave Mark, MacTech Magazine Regular Contributing Author
Note: Source code files accompanying article are located on MacTech CD-ROM orsource code disks.
In last month’s column, we expanded our event-handling repertoire to include
activate, update, and suspend/resume events. By now, you should feel pretty
comfortable with the Event Manager. If you haven’t already, put down this column and
go read the Event Manager chapters in Inside Macintosh, Volumes I and VI.
In this month’s column, we’re going to take a look at the Menu Manager, the part
of the Toolbox responsible for your program’s menus.
The Pull-Down Menu
Almost every single Macintosh program comes complete with its own menu bar,
the strip of menu titles along the top of your Mac’s main screen. The menu bar contains
one menu title for each of your program’s current pull-down menus. Figure 1 shows
the Finder’s menu bar with the File menu pulled down.
Figure 1. A menu bar with a pull-down menu exposed.
A proper menu bar always features at least three menus, [Missing image]ile, and Edit. When
a menu is pulled-down, its menu items will be drawn. In addition to the item’s name, a
menu item may feature an icon, as well as a command-key equivalent. The
command-key equivalent, when typed by the user, simulates the selection of the
equivalenced menu item. For example, in the menu in Figure 1, the command-key
equivalent W will cause the Close Window item to be selected from the File menu.
Items may be dimmed, or disabled, which pr events the user from selecting them.
If an item is disabled, it is drawn in gray. A normal item is said to be enabled.
You may have noticed that some menu items are drawn followed by an ellipsis, a
sequence of three dots (...). The ellipsis tells the user that this item will cause a dialog
box to appear, prompting the user for further information. We’ll get to dialog boxes in
a later column.
Working With the Menu Manager
The Menu Manager consists of a series of routines designed to work with two
resource types, MBAR and MENU. The MBAR resource links together a series of MENU
resources to form a menu bar. A MENU resource is used to completely specify a menu,
including all the menus items and any associated icons and command-key equivalents.
Here’s a quick tour through the main Menu Manager routines.
Once you’ve built your MBAR and MENU resources (you’ll see how in a bit),
you’re ready to start programming. You’ll start off by creating a menu initialization
routine. In it, you’ll call GetNewMBar(), which builds a menu list, based on the
MENUs specified in an MBAR resource. A menu list is the data structure the Menu
Manager bases a menu bar on. Once the menu list is built, pass it to SetMenuBar() to
make it the current menu bar. Note that you can have more than one menu bar, but
only one current menu bar.
Once you’ve specified a current menu bar, draw the menu bar by calling
DrawMenuBar(). Now you’re ready to work with your individual menus.
Modifying the Menu Bar
There will be times when the menu bar described in your MBAR resource won’t
be enough. For example, you might have a menu that appears only if the user has color
turned on, or when a certain type of window is open. You can add a menu to or delete a
menu from the menu bar. To add a menu to the menu bar, call GetMenu() to load a new
MENU resource into memory, into the list of available menus (but not into the current
menu bar). GetMenu() returns a MenuHandle which you can pass to InsertMenu().
InsertMenu() inserts the specified menu into the current menu bar. To delete a menu
from the menu bar, call DeleteMenu().
Another routine you might find useful is GetMHandle(), which returns a
MenuHandle to a menu already loaded into memory. Basically, you’ll use GetMenu() to
get a handle to a menu that’s never been loaded, and GetMHandle() to get a handle to a
previously loaded menu. Use InsertMenu() to add a loaded menu into the current menu
bar. Remember, whenever you change the menu bar, call DrawMenuBar() to bring
your changes to life. You only need to call DrawMenuBar() when you change the
current menu bar, not when you change a menu’s items.
Changing a Menu Item’s Appearance
The Menu Manager gives you a set of routines you can use to customize your
menus. For example, the routines EnableItem() and DisableItem() allow you to enable
or disable a menu item. You can use the routine AddResMenu() to add all the resources
of a specific type as menu items. There are two specific times when this comes in
handy. To add all the fonts to a menu, pass ‘FONT’ to AddResMenu(). To add all the
standard apple menu items to the apple menu, pass ‘DRVR’ to AddResMenu(). Why
‘DRVR’? Prior to System 7, all the items in the apple menu were desk accessories,
which have a resource type of ‘DRVR’. Even though System 7 allows you to add more
than DA’s to your apple menu, AddResMenu() still works properly, as you’ll see by
this month’s program.
You can use SetItem() to change the name of a menu item. You can use GetItem()
to retrieve an item’s name. CheckItem() lets you place or remove a check mark from
an item and SetItemMark() lets you place or remove any character from the system
font next to an item. GetItemMark() retrieves an item’s mark.
SetItemIcon() and GetItemIcon() set and get the resource ID of any icon
associated with an item. For some reason, the resource ID returned by GetItemIcon()
is 256 less than the icon’s actual resource ID. This means that your icon’s resource ID
will range from 257 to 511.
SetItemStyle() and GetItemStyle() are used to set and get the style of an item’s
name. We’ll make use of these function’s in next month’s program.
Detecting a Menu Selection
There are two ways a user can select from a menu. They can click the mouse in
the menu bar or they can type a command-key equivalent. You’ll detect a mouse click
in the menu bar by detecting a mouseDown event that occurred inMenuBar. If this
happens, you’ll call a routine called MenuSelect(). MenuSelect() tracks your mouse,
pulling down menus, highlighting items, and, if necessary, selecting an item from a
menu. MenuSelect() returns a value that indicates the menu and item that was selected.
If a keyDown or autoKey event occurs, you’ll check to see if the command-key
was down when the event occurred. If so, you’ll call a routine called MenuKey() which
translates the key to a value that indicates the menu and item that was selected.
Whether the menu/item was selected via a keyDown or a mouseDown in the menu
bar, it will be translated into a menu/item value. You’ll pass this menu/item value on
to your own routine which processes the menu selection. Once you process the menu
selection, call HiliteMenu() to uninvert the menu’s title, which was left inverted by
MenuSelect() or MenuKey().
MenuMaster
OK, that’s about it for Menu Manager routines. There are a few that we haven’t
discussed and you should definitely read the Menu Manager chapter in Inside
Macintosh, Volume I. For now, let’s get into this month’s program, MenuMaster.
Create a folder named MenuMaster in your development folder. Now go into
ResEdit and create a new resource file named MenuMaster.π.rsrc in the MenuMaster
folder. Select Create New Resource from the Resource menu and create a new MBAR
resource. When the MBAR window appears, click on the row of *’s (Figure 2) and type
K to create a new MENU field. When the new field appears, type in the MENU id 128.
Figure 2. Click on the *’s and type K to add a MENU to the MBAR.
When the second row of *’s appears, click on it and type K to create a second
MENU field. Repeat this process till your MBAR looks like the one in Figure 3.
Close the MBAR window, and close the MBAR picker window. Next, select Create
New Resource from the Resource menu and create a MENU resource. When the MENU
editing window appears, click on the radio button to create an apple menu. Hit a
carriage return and type in the text About MenuMaster... followed by another carriage
return. Now click on the separator line radio button to insert a separator line after the
About MenuMaster... item. Since separator lines are never enabled, they’ll never be
chosen by the user. Your menu should look like the one shown in Figure 4.
Figure 3. The filled out MBAR resource with four MENU resource ids.
Figure 4. Specifications for MENU 128.
Close the editing window and type K to create a new MENU resource. This time,
instead of clicking on the radio button, type the word File in the Title field and hit a
carriage return. Next type the word Quit and type the letter Q in the Cmd-Key field
that appears. You’ve just made Q a command-key equivalent to the File menu’s Quit
item. Your menu should look like the one shown in Figure 5.
Figure 5. Specifications for MENU 129.
Close the editing window and create another MENU, using the MENU shown in
Figure 6 as a guide. Be sure to add the separator line after the Undo item, and to type in
the four command-key equivalents.
Figure 6. Specifications for MENU 130.
Close the editing window and create yet another MENU, according to the
specifications shown in Figure 7. Be sure to include the three separator lines. If you
forget one, you can add one at the end of the menu, then click and drag it to its proper
position. Notice that the item labeled Enable Previous Item has been disabled. Do this
by making sure the Enabled check box is unchecked for that item only.
Figure 7. Specifications for MENU 131.
Finally, create one more MENU. Use the title Extra Menu and add the item Delete
This Menu (Figure 8).
Figure 8. Specifications for MENU 132.
Next, click on the item Delete This Menu and select Choose Icon... from the MENU
menu. You’re going to attach an icon to the menu item. When the dialog box appears,
click on the Small Icons radio button, then click the New button.
Figure 9. The Choose Icon... dialog box.
When the SICN editing window appears, go to town. Create whatever kind of small
icon your heart desires. Get creative. Figure 10 shows my SICN, lifted from the
Macintosh Programming Primer.
Figure 10. A SICN with a resource ID of 257.
If you preferred, you could use an ICON or a reduced ICON resource instead.
Personally, I prefer SICNs or none at all. Once you are done editing your SICN, close
the SICN editing window. You can get a preview of the menu by clicking on the
prototype that appears on the right end of the menu bar. Your SICN should be in place.
If not, be sure your SICN has a resource ID of 257. Icons attached to menu items must
have an ID between 257 and 511.
Once you are happy with your MENU, close the MENU editing window. You may
have noticed that you’ve created MENUs with resource IDs 128 through 132, while
your MBAR only includes MENUs with IDs from 128 to 131. We’ll add this extra menu
to our menu bar from inside our program.
Well, that’s about it for resources. Quit ResEdit, making sure you Save your
changes.
Creating the MenuMaster Project
Launch THINK C and create a new project called MenuMaster.π in the
MenuMaster folder. Add MacTraps to the project, then select New from the File menu to
create a new source code window. Type in the following source code:
/* 1 */
#include
#define kBaseResID 128