Previous Book Contents Book Index Next

Inside Macintosh: Programmer's Guide to MacApp / Part 2 - Working With MacApp
Chapter 12 - Working With Menus


Overview

In a Macintosh application, users activate many tasks by choosing a command from a menu. Most Macintosh applications provide at least these three standard menus: the Apple menu, the File menu, and the Edit menu. If you include the Apple menu, two more menus appear automatically on your application's menu bar: the Macintosh Menu Manager adds the Application menu, and the Help Manager adds the Help menu.

With MacApp, you specify menus and menu items in your resource definition file, using two types of resources:

When your application is launched, MacApp's Menu Manager reads your 'MBAR' and 'CMNU' resources and builds tables to store the information found in them. MacApp uses this menu data to manage your application's menus and to respond to user menu choices.

MacApp provides default versions of several menus in its resource definition files, including the File and Edit menus. Your application can use MacApp's default menu resources, modify MacApp's resources, or create its own menu resources.

MacApp also provides the TMenuView class and its TTearOffMenuView subclass to help your application implement tear off menus.

Working With Menu Resources

This section describes how to specify your application's menus using menu resources.

MacApp Menu ID Constants

MacApp defines menu constants that you can use in both your code files and your resource definition files. Several of these constants are shown in Table 12-1.
Table 12-1 Menu ID constants
Menu nameMenu ID constantValue
ApplemApple1
FilemFile2
EditmEdit3
(MacApp manages menus between mFirstMenu and mLastMenu)mFirstMenu1
(don't define a Menu ID greater than this)mLastMenu63
(the Buzzwords menu doesn't appear in your menu bar; it is used to supply text for certain Undo menu items)mBuzzwords128

The mApple, mFile, and mEdit constants are used in 'MBAR' resources. The mFirstMenu and mLastMenu constants are used by MacApp when processing menu commands. The mBuzzwords constant is the ID for a special menu that is described in "The Buzzwords 'CMNU' Resource," beginning on page 305.

The Menu Bar Manager

The TMenuBarManager class manages menu-bar operations and provides routines to add menu items, add help menu items, delete menu items, and make changes to the application's menu bar. The application object creates a menu-bar manager object in the IApplication method. Your application can access it through the global variable gMenuBarManager.

The 'MBAR' Resource

You use an 'MBAR' resource to specify the menus that appear in your application's menu bar. The menu-bar resource stores a menu ID for each application menu that should appear in the menu bar. MacApp's predefined menu ID constants are shown in Table 12-1. The value of a menu ID for a menu handled by MacApp must be in the range specified by mApple and mLastMenu (that is, from 1 to 63).

The following is a typical menu-bar resource, taken from the IconEdit sample application. It includes the three standard menus--Apple, File, and Edit--as well as an Icon menu for specifying icon operations:

resource 'MBAR' (kMBarDisplayed,
#if qNames
"IconEdit",
#endif
purgeable) 
{
    {mApple; mFile; mEdit; mIcon} 
};
The definition for mIcon is found in the file IconEdit.r:

#define mIcon4
MacApp defines four constants used in constructing 'MBAR' resources:

kMBarDisplayed
You create one 'MBAR' resource with this ID. MacApp reads the resource and installs the specified menus in your application's menu bar.
kMBarNotDisplayed

You can create one 'MBAR' resource with this ID. MacApp reads in the resource but does not automatically display it. You can call on the menu-bar manager to change to the menu bar specified by this resource.
kMBarHierarchical
You supply one 'MBAR' resource with this ID for each hierarchical menu in your application (see page 316).
kMBarDebug
MacApp uses this constant to define a debug 'MBAR' resource. The Debug menu supplies menu commands for options such as turning performance monitoring on or off and displaying a window of debug flags you can modify.
For information on how to build a debug version of your application, see "Common Command-Line Options," beginning on page 678 in Appendix A.

Defining Menu Contents With a 'CMNU' Resource

A 'CMNU' resource specifies the items that appear in a menu and contains a list of attributes for each menu item. These attributes specify

Table 12-2 shows the MacApp constants that help you fill in this information.
Table 12-2 Menu item constants
Constant nameEffect on menu item
noIconNo icon shown
noKeyNo key equivalent
noMarkNo mark
checkMark with check
plainPlain text

The following 'CMNU' resource describes MacApp's default Edit menu:

resource 'CMNU' (mEdit,
#if qNames
"mEdit",
#endif
purgeable) {
   mEdit,
   textMenuProc,
   EnablingManagedByMacApp,
   enabled,
   "Edit",
   {
   "Undo",     noIcon, "Z",noMark, plain, cUndo;
   "-",        noIcon, noKey,noMark, plain, nocommand;
   "Cut",      noIcon, "X",noMark, plain, cCut;
   "Copy",     noIcon, "C",noMark, plain, cCopy;
   "Paste",    noIcon, "V",noMark, plain, cPaste;
   "Clear",    noIcon, noKey,noMark, plain, cClear;
   "Select All",noIcon, "A",noMark, plain, cSelectAll;
   "-",        noIcon, noKey,noMark, plain, nocommand;
   "Show Clipboard",noIcon,noKey,noMark, plain, cShowClipboard
   }
};
In the 'CMNU' description above

The Buzzwords 'CMNU' Resource

MacApp helps automate the process of implementing undoable commands by supplying text for the Undo menu item. For example, after a user performs a Paste operation, MacApp puts the words "Undo Paste" in the Edit menu. MacApp can put the word "Paste" in the menu because the Paste menu command is defined in the 'CMNU' resource for the Edit menu.

However, some commands that can be undone, such as drawing with the mouse, may not be listed in any menu. To display "Undo Drawing" in the menu when a drawing command can be undone, you have to inform MacApp of the name to associate with the command number for drawing. You supply this information in a 'CMNU' resource called the Buzzwords menu.

The Buzzwords menu has the same format as other 'CMNU' resources, but it always has a resource ID of 128 (defined by the constant mBuzzwords) and a menu title of Buzzwords. The Buzzwords menu never appears in your application's menu bar--you use it only to supply information to MacApp.

The following is the Buzzwords 'CMNU' resource from the IconEdit sample application. Note that each entry contains a buzzword phrase and a command-number constant. For example, the word "Drawing" is associated with the constant cDrawCommand. This tells MacApp to show the menu phrase "Undo Drawing" for a drawing command.

resource 'CMNU' (mBuzzwords) {
   mBuzzwords,
   textMenuProc,
   allEnabled,
   enabled,
   "Buzzwords",
    {
      "Page Setup Change", noIcon, noKey, noMark, plain,
                                       cChangePrinterStyle;
      "Drawing", noIcon, noKey, noMark, plain, cDrawCommand;
      "Set Color", noIcon, noKey, noMark, plain, cSetColor
   }
};

Enabling and Disabling Menu Items

If a menu command is currently available, the menu item for that choice should be enabled. If a menu command is not currently available, the menu item should be disabled and its text dimmed. For example, if nothing in the active view is selected, the Cut command on the Edit menu is normally disabled and its text is dimmed.

MacApp calls gApplication->SetupTheMenus whenever the status of menu items might need to be updated, including when the user clicks in the menu bar or when a key event is received. The SetupTheMenus method first disables each menu item on each menu MacApp manages (the Apple menu is managed by the system), then calls the HandleSetupMenus method of the current target object.

The HandleSetupMenus method causes the DoSetupMenus method to be called for each behavior object and event handler in the target chain, giving each object a chance to enable the menu items it can handle. When this process is finished, only those menu items that can be handled by objects in the current target chain are enabled.

Figure 12-1 shows how event-handler objects and behavior objects in the target chain enable menu items.

Figure 12-1 Enabling menu items

The DoSetupMenus method is inherited by classes that descend from the TEventHandler class and by classes that descend from the TBehavior class. When you define a class that descends from one of these classes, you override the DoSetupMenus method to enable the menu items your class can handle.

You enable a specific menu item by calling the Enable routine and passing the command constant associated with the menu item. For example:

void TYourClass::DoSetupMenus()
{
   Inherited::DoSetupMenus();
   Enable(cMyCommand, TRUE);
}
The Enable routine is used to enable or disable the menu item with the specified command number. You can also enable menu items with the EnableCheck routine, which enables the item and adds a checkmark next to it.

Note
You don't normally need to disable menu items in a DoSetupMenus method, because MacApp disables all items before calling DoSetupMenus.
To enable menu items with a behavior object, you define a subclass of TBehavior and override the DoSetupMenus method. Your application creates an instance of the new behavior class and associates it with an event-handler object by calling the AddBehavior method of the event handler. You also override methods such as DoMenuCommand or DoKeyEvent in your behavior class to handle the menu choices you have enabled.

Processing a Menu Choice

Once you have defined menu resources to describe your application's menus, MacApp takes care of displaying the menus and dispatching user menu choices.

When a user chooses a menu command, MacApp calls the HandleMenuCommand method of the current target object, passing the command number associated with the menu choice. If the target object or a behavior object attached to it can't handle the choice, it passes it on to the next object in the target chain. If no object in the target chain handles the menu choice, it is ignored. This process is shown in Figure 5-4 on page 110.

You use event-handler objects and behavior objects to respond to menu choices. These classes are described in Chapter 5, "Events and Commands."

Certain objects in an application typically handle specific menu commands:

Changing Menus From Your Application

MacApp provides routines to change the appearance of menus while your application is running:

SetCommandName
The SetCommandName routine changes a menu item's text.
SetStyle
The SetStyle routine changes a menu item's font style.
SetCommandIcon
The SetCommandIcon routine displays a menu item icon.
EnableCheck
The EnableCheck routine checks or unchecks a menu item, and also enables or disables it.
You can read about these routines in the MacApp Class and Method Reference.

Working With Pop-Up Menus

Pop-up menus are useful for presenting a list of choices. For example, you might use a pop-up menu to set the baud rate in a modem-setup dialog box or to choose the line spacing in a word-processing program.

A pop-up menu appears as a rectangle with a 1-pixel border and a 1-pixel drop shadow. Pop-up menus are identified by a downward-pointing triangle that appears in the pop-up box. The title of the pop-up menu appears next to the pop-up box. Figure 12-2 shows a simple pop-up menu.

Figure 12-2 Simple pop-up menu

To open a pop-up menu, the user presses the mouse button while the cursor is over the pop-up title or pop-up box. The menu "pops up," displaying the items in the menu with the current item highlighted. As the user drags the cursor through the menu, the item under the cursor is highlighted. When the user releases the mouse button, the highlighted item becomes the current item.

Figure 12-3 shows a pop-up menu in its closed and open states. You can read more about pop-up menus in Inside Macintosh: Macintosh Toolbox Essentials and in the Macintosh Human Interface Guidelines.

Figure 12-3 A pop-up menu in its closed and open states

The TPopup Class

You implement a pop-up menu with the MacApp class TPopup or with a subclass you define. The TPopup class is a subclass of TControl, which is in turn a descendant of TView. The TPopup class defines these fields:

fStrListID /fIndex
Specifies the pop-up menu's title in a string resource list ('STR#').
fMenuID
Specifies a resource ID of a 'MENU' or 'CMNU' resource for the pop-up menu.
fCurrentItem
Specifies the currently chosen menu item.
fItemOffset
Stores the width of the pop-up title area (from the left edge of the view to the pop-up menu view).
Figure 12-4 shows how a pop-up menu view is drawn. When a TPopup object is created, its pop-up menu view is initialized and installed in the specified superview. The menu title is drawn starting at fItemOffset, using the justification specified by the fTitleJust field (the default is left justified). The pop-up selector is drawn to the right of fItemOffset, with its width and height determined by the menu dimensions.

Figure 12-4 A pop-up menu view

Responding to a User Menu Choice

When a user clicks a pop-up menu, a mouse-down event is sent to the window containing the view. The DoMouseCommand method of the TCtlMgr ancestor of TPopup tracks the mouse by calling the Toolbox routine TrackControl. If the user selects an item in the pop-up menu, DoMouseCommand sets the pop-up's fLongVal field to the number of the selected menu item, then calls HandleEvent, passing an event constant. This results in a call to the pop-up's DoEvent method.

The event constant passed to HandleEvent comes from the pop-up's fEventNumber field (defined in the TCtlMgr parent class of TPopup). For a pop-up menu, it defaults to mPopupHit. The TPopup class doesn't override DoEvent, so to respond to a user menu choice, you can either define a subclass of TPopup and override the DoEvent method, or override DoEvent in the view class of the pop-up's superview.

For example, for a pop-up menu displayed in a dialog view, you can override the DoEvent method of the dialog view, as shown in the following code sample:

void TTestDialogView::DoEvent(EventNumbereventNumber,
                        TEventHandler*source,
                        TEvent*     event) // Override.
{
   // If the event concerns our pop-up menu...
   if((eventNumber == mPopupHit) && (source == fMyPopup))
   {
      // Get the command number associated with the selected
      // pop-up menu item.
      aCommandNumber = ((TPopup*)source)->GetCurrentCommand();
      switch (aCommandNumber)
      {
         // If it's a command number we're interested in, process it.
         case cMyCommand:
               // Code to respond to the command constant.
         .
         .
         .
      } // End switch.
   }      break;
}  // TTestDialogView::DoEvent
The GetCurrentCommand method calls CommandFromMenuItem to get a command number for the chosen pop-up menu item. If you have defined your pop-up menu with a 'CMNU' resource, as described on page 303, you can associate command constants with pop-up menu items, just as you would with items on a standard menu.


Previous Book Contents Book Index Next

© Apple Computer, Inc.
25 JUL 1996