Legacy Documentclose button

Important: The information in this document is obsolete and should not be used for new development.

Previous Book Contents Book Index Next

Inside Macintosh: Macintosh Toolbox Essentials /
Chapter 3 - Menu Manager / Using the Menu Manager


Creating a Menu

You use various Menu Manager routines to set up the menus and the menu bar
for your application. You can use any of these methods to create pull-down menus for
your application:

Whenever possible you should define your menus in menu ('MENU') resources and your menu bar in a menu bar ('MBAR') resource to make your application easier
to localize.

To create a hierarchical menu, you need to create descriptions of the submenu and the menu to which the submenu is attached. Usually you create the description of both menus in 'MENU' resources. You typically read in the description of the hierarchical menu using GetNewMBar (if you also provide an 'MBAR' resource). To read in the description of the submenu and insert it in the current menu list, use the GetMenu function and InsertMenu procedure.

To create a pop-up menu, create descriptions of the pop-up menu and its menu items, create a control that uses the pop-up control definition function, and associate the control with a window or dialog box. You can display and manage the pop-up menu using the Dialog Manager or Control Manager routines.

Once the Menu Manager creates a menu for your application, if necessary you can add additional menu items to the menu using AppendMenu, InsertMenuItem, InsertResMenu, or AppendResMenu. You can use various Menu Manager routines to change the appearance of menu items.

The next sections describe how to create 'MENU' and 'MBAR' resources. "Creating a Hierarchical Menu" on page 3-55 describes how to create a menu that has a submenu, and "Creating a Pop-Up Menu" on page 3-58 describes how to create pop-up menus.

Creating a Menu Resource

Usually you should define your menus in menu ('MENU') resources so that you can easily localize the menu titles and menu items for other languages, cultures, or regions. A 'MENU' resource defines the menu title of a menu and the characteristics of menu items in a menu. Listing 3-1 shows a sample 'MENU' resource in Rez format for an application's Apple menu. (Rez is a resource compiler available with MPW. You can also define menus using a resource utility, such as ResEdit, available from APDA.)

Listing 3-1 Rez input for a 'MENU' resource for the Apple menu

#define mApple 128
resource 'MENU' (mApple, preload) { /*resource ID, preload resource*/
      mApple,                       /*menu ID*/ 
      textMenuProc,                 /*uses standard menu definition */ 
                                    /* procedure*/
      0b1111111111111111111111111111101,  /*enable About item, */
                                          /* disable divider, */
                                          /* enable all other items*/
      enabled,                      /*enable menu title*/
       apple,                       /*menu title*/
      {
                                    /*first menu item*/
            "About SurfWriter...",       /*text of menu item */
                                       /* (includes ellipsis)*/
                                       /*item characteristics follow*/
                  noicon,              /*icon number (if any) or */
                                       /* script code (if any)*/
                  nokey,               /*keyboard equivalent (if any) */
                                       /* or submenu (if any) or */
                                       /* small or reduced icon (if any)*/
                  nomark,              /*marking character (if any) or */
                                       /* menu ID of submenu (if any)*/
                  plain;               /*style of menu item text*/
                                    /*second menu item*/
            "-",                       /*item text (divider)*/
                  noicon, nokey, nomark, plain  /*item characteristics*/
      }
};
You should also define help balloons for each of your application's menu items and each menu title when you create your menus. (Figure 3-21 on page 3-35 shows help balloons for an application's Cut command.) You define the help balloons for your application's menus in 'hmmu' resources. See the chapter "Help Manager" in Inside Macintosh: More Macintosh Toolbox for examples of how to create 'hmmu' resources.

Listing 3-1 defines the resource ID of the Apple menu as 128. You can use any number equal to or greater than 128 as a resource ID for a menu. By convention, many applications use 128 as the resource ID of the first menu in the application's menu bar (the Apple menu) and use sequential numbers for the resource IDs of following menus.

Listing 3-1 also defines the menu ID of the Apple menu as 128. Once your application creates the menu, the Menu Manager uses the defined menu ID to refer to this menu. The number you define for the menu ID of a menu does not have to match the resource ID of the menu, but it is usually more convenient to use the same number. You can use any number greater than 0 for the menu ID of a pull-down or pop-up menu; submenus of an application can only use menu IDs from 1 through 235; submenus of a desk accessory must use menu IDs from 236 through 255.

The listing specifies that this menu uses the standard menu definition procedure. If you choose to create your own menu definition procedure, list its resource ID instead of the textMenuProc constant.

After the resource ID of the menu definition procedure is a 32-bit number (expressed as
a 31-bit field followed by a Boolean field), where bits 1-31 indicate if the correspond- ing menu item is disabled or enabled, and bit 0 indicates whether the menu is enabled
or disabled.

The listing specifies in the 31-bit field that the first menu item should be enabled, that the second menu item should be disabled, and that the following menu items (item numbers 3 through 31) should be enabled when the menu is first created. After creating a menu, your application can enable or disable menu items using the EnableItem or DisableItem procedure. If a menu contains more than 31 items, the Menu Manager automatically enables all items following the 31st item when the menu is enabled. Your application cannot disable any individual items following the 31st item. However, you can disable all items, including items after the 31st item, by disabling the entire menu.

Listing 3-1 specifies that the menu title should be enabled when it is first created.
Your application can also disable or enable the menu title using the DisableItem or EnableItem procedure. When you disable a menu using the DisableItem procedure, the Menu Manager disables all menu items in the menu (including any items following the 31st item) and dims the title of the menu.

The resource listing identifies the title of the menu using the constant apple. If you specify the apple constant as the title, the Menu Manager uses a small Apple icon as the title of the menu. The Menu Manager uses a color Apple icon if the monitor is set to display colors. The listing then defines the characteristics of each menu item in the menu. For each menu item, you need to define the text and any other characteristics of the menu item. For example, Listing 3-1 defines the first item in the Apple menu as the About command; note that the text of this menu item specifies three ellipsis points (...). Specify three ellipsis points following the text of a menu command if your application displays a dialog box requesting information from the user before performing the command. In general, you should not use ellipses if your application displays a confirmation alert after the user chooses a menu command; the About command is an exception to this guideline.

Listing 3-1 defines other characteristics of the About command--it doesn't have an
icon to the left of the menu item text, it doesn't have a keyboard equivalent, it doesn't have any mark to the left of the menu item text, and the font style of the menu item
text is plain.

By specifying various combinations of values in the icon field and keyboard equivalent field, you can define an icon (normal, small, reduced, or color), a keyboard equivalent, a submenu, or the script code of a menu item. Note that some characteristics are mutually exclusive (for example, an item can have a keyboard equivalent or submenu, but not both), as described in the following paragraphs. Table 3-6 on page 3-48 summarizes how the Menu Manager interprets these item characteristics.

Table 3-6 Table 3-6 Specifying submenus, script codes, reduced icons, small icons, and color icons of a menu item in a menu resource
Keyboard equivalent fieldIcon fieldMarking character fieldDescription
$1B Menu ID of submenuIndicates the item has a submenu. The marking character field specifies the
menu ID of the submenu.
$1CScript code of item text Indicates the item text uses the script defined by the script code specified in the icon field.
$1DIcon number of 'ICON'resource Indicates the item has an icon defined by an 'ICON' resource and that it should be reduced to fit in a 16-by-16 bit rectangle.
$1EIcon number
of 'SICN' resource
 Indicates the item has an icon defined by an 'SICN' resource.
$00 or >$20Icon number of 'ICON' or 'cicn' resource Indicates the item has an icon defined
by an 'ICON' or a 'cicn'resource.
(A value greater than $20 in the
keyboard equivalent field specifies the item's keyboard equivalent.)

To assign an icon to a menu item, specify an icon number in place of the noicon constant. The icon number you specify should be a number from 1 through 255 (or from 1 through 254 for small icons and reduced icons); add 256 to your icon number and use the result for the resource ID of the color icon ('cicn') resource, icon ('ICON') resource, or small icon ('SICN') resource that describes the icons for the menu item. You must define the icon for a menu item in a 'cicn', an 'ICON', or an 'SICN' resource; the Menu Manager uses only these types of resources for icons you define for your menu items. The Menu Manager first looks for a 'cicn' resource with the calculated resource ID and uses that icon if it finds it. If it doesn't find a 'cicn' resource (or if the computer doesn't have Color QuickDraw) and the keyboard equivalent field specifies $1E, the Menu Manager looks for an 'SICN' resource with the calculated resource ID. Otherwise, the Menu Manager looks for an 'ICON' resource and plots it in a 32-by-32 bit rectangle, unless the keyboard equivalent field contains $1D. If the keyboard equivalent field contains $1D, the Menu Manager reduces the icon to fit in a 16-by-16
bit rectangle.

If you provide an 'ICON' resource and specify the nokey constant or a value greater than $20 as the keyboard equivalent, the Menu Manager enlarges the rectangle of the entire menu item to fit the 32-by-32 bit 'ICON' resource. If you specify a value of $1D as the keyboard equivalent of the menu item, the Menu Manager reduces the 'ICON' resource to fit in a 16-by-16 bit rectangle. If you provide an 'SICN' resource and specify a value of $1E as the keyboard equivalent of a menu item, the Menu Manager plots the small icon in a 16-by-16 bit rectangle. If you provide a 'cicn' resource, the Menu Manager automatically enlarges the enclosing rectangle of the menu item according to the rectangle specified in the 'cicn' resource. (For the Apple and Application menus, the Menu Manager automatically reduces the icon to fit within the enclosing rectangle of a menu item or uses the appropriate icon from the application's icon family, such as an 'ics8' resource, if one is available.) See the chapter "Finder Interface" in this book for details on how to create icons for your application.

To assign a keyboard equivalent to a menu item, specify the 1-byte character that the user types in addition to the Command key in place of the nokey constant in your resource definition for the menu item. If your application attaches a submenu to a menu item, then specify the hierarchicalMenu constant in place of the nokey constant. A menu item can have either a keyboard equivalent or submenu defined for it, but not both. To indicate that a menu item has an icon that is defined in an 'SICN' resource, specify $1E in place of the nokey constant. To indicate that a menu item has an icon that is defined in an 'ICON' resource and that the Menu Manager should reduce this icon to a 16-by-16 bit rectangle, specify $1D in place of the nokey constant. Menu items that have small icons or reduced icons cannot have keyboard equivalents.

To set the script code of a menu item's text, specify $1C in place of the nokey constant and define the desired script code in place of the noicon constant. If an item contains $1C in its keyboard equivalent field and a script code in its icon field, the Menu Manager draws the item's text in the script identified by the script code value if the corresponding script system is installed. If you do not specify a script code for a menu item, the Menu Manager displays the menu item's text in the system font of the current system script. For Roman scripts, the system font is Chicago and the system font size is 12.

To assign a mark that appears to the left of the menu item text and to the left of any
icon, specify the marking character in place of the nomark constant in your resource definition. If the menu item has a submenu, then specify the menu ID of the submenu in place of the nomark constant. Submenus of an application must use menu IDs from
1 through 235; submenus of a desk accessory must use menu IDs from 236 through 255. Note that defining the menu ID of a submenu in a 'MENU' resource does not attach the submenu to its menu. You must use the GetMenu function and InsertMenu procedure to do this. "Creating a Hierarchical Menu," which begins on page 3-55, gives information on attaching a submenu to its menu.

To assign a font style to a menu item, in your 'MENU' resource use the constants bold, italic, plain, outline, and shadow to get their corresponding styles.

Listing 3-1 defines the second menu item as a divider. When you use a hyphen as the first character in the string that defines the text of a menu item, the Menu Manager creates a divider that extends across the entire width of the menu item. You cannot assign any other characteristics to a divider.

The 'MENU' resource for the Apple menu does not list any other menu items. Use the AppendResMenu procedure to add the desktop items to the Apple menu after your application creates the menu. See "Adding Items to the Apple Menu" on page 3-70 for more information.

Once you create a menu, you can append additional items to it using the AppendMenu, InsertMenuItem, InsertResMenu, or AppendResMenu procedure. You can also change the characteristics of individual menu items using Menu Manager routines. See "Changing the Appearance of Items in a Menu" on page 3-59 for more information.

Figure 3-12 on page 3-30 shows a typical Edit menu for an application. Listing 3-2 shows a 'MENU' resource for this Edit menu.

Listing 3-2 Rez input for a 'MENU' resource for an Edit menu

#define mEdit 130
resource 'MENU' (mEdit, preload) {     /*resource ID, preload resource*/
   mEdit,                              /*menu ID*/
   textMenuProc,                       /*uses standard menu definition */ 
                                       /* procedure*/
   0b0000000000000000001001000000000,  /*enable/disable first 31 menu */
                                       /* items as appropriate*/
   enabled,                            /*enable title*/
   "Edit",                             /*text of menu title*/
    {                                  /*menu items*/
   "Undo",  noicon, "Z",   nomark, plain; /*keyboard equivalent Command-Z*/
   "-",     noicon, nokey, nomark, plain;
   "Cut",   noicon, "X",   nomark, plain; /*keyboard equivalent Command-X*/
   "Copy",  noicon, "C",   nomark, plain; /*keyboard equivalent Command-C*/
   "Paste", noicon, "V",   nomark, plain; /*keyboard equivalent Command-V*/
   "Clear", noicon, nokey, nomark, plain; 
   "Select All",
            noicon, "A",   nomark, plain; /*keyboard equivalent Command-A*/
   "-",     noicon, nokey, nomark, plain;
   "Create Publisher...",
            noicon, nokey, nomark, plain;
   "Subscribe To...",
            noicon, nokey, nomark, plain;
   "Publisher Options...",
            noicon, nokey, nomark, plain;
   "-",     noicon, nokey, nomark, plain;
   "Show Clipboard",
            noicon, nokey, nomark, plain 
      }
};
Listing 3-2 defines the resource ID of the Edit menu as 130, defines the menu ID of the Edit menu as 130, and specifies that this menu uses the standard menu definition procedure. The listing defines the initial enabled state of the first 31 menu items and
also specifies that the menu title should be enabled when it is first created.

The resource listing defines the title of the menu, Edit. It then defines the characteristics of each menu item in the menu. For each menu item, you need to specify the text of the menu item and any other characteristics of the menu item. For example, Listing 3-2 defines the first item in the Edit menu as the Undo command with these characteristics: there is no icon to the left of the menu item text, the menu item has a keyboard equivalent of Command-Z, it does not have any mark to the left of the menu item text, and the style of the menu item text is plain. The listing defines the second menu item as a divider line. It defines the Cut, Copy, and Paste commands; specifies keyboard equivalents for each of them; and defines the rest of the items in the menu.

Listing 3-3 shows another example of a resource description of a menu, the File menu of a typical application.

Listing 3-3 Rez input for a 'MENU' resource for a File menu

resource 'MENU' (mFile, preload) {  
      mFile, textMenuProc,          
      0b0000000000000000000010000000000,  
      enabled, 
      "File",                       
      {                                      
         "New",         noicon, "N",   nomark, plain; 
         "Open...",       noicon, "O",   nomark, plain; 
         "-",           noicon, nokey, nomark, plain; 
         "Close",       noicon, "W",   nomark, plain; 
         "Save",        noicon, "S",   nomark, plain; 
         "Save As...",    noicon, nokey, nomark, plain; 
         "-",           noicon, nokey, nomark, plain; 
         "Page Setup...", noicon, nokey, nomark, plain; 
         "Print...",      noicon, "P",   nomark, plain; 
         "-",           noicon, nokey, nomark, plain;
         "Quit",        noicon, "Q",   nomark, plain  
      }
};

Creating a Menu Bar Resource

You typically define your application's menu bar using a menu bar ('MBAR') resource. Listing 3-4 shows an 'MBAR' resource, in Rez format, for a sample application.

Listing 3-4 Rez input for an 'MBAR' resource

#define rMenuBar     128
#define mApple       128
#define mFile        129
#define mEdit        130
resource 'MBAR' (rMenuBar, preload) {/*resource ID, preload*/
   /*menus appear in the order listed here*/
   { mApple, mFile, mEdit };        /*resource IDs for menus in */
                                    /* this menu bar*/
};
Listing 3-4 defines the 'MBAR' resource with resource ID 128. This 'MBAR' resource defines the order and resource IDs of the menus contained in it; it defines its first
three menus as the menus with resource IDs 128, 129, and 130. The Menu Manager
uses the assigned resource IDs to read in the menus when it creates a menu bar from
an 'MBAR' resource.

Setting Up Your Application's Menu Bar

To create a menu list as defined in an 'MBAR' resource, use the GetNewMBar function. For each menu defined by the 'MBAR' resource, the GetNewMBar function creates a menu record for the menu, creates each menu according to its resource definition in its corresponding 'MENU' resource, and inserts each menu into the new menu list. The GetNewMBar function returns a handle to the created menu list. For example, this code creates a menu list for the menu bar defined by the 'MBAR' resource with resource ID 128 (defined by the constant rMenuBar):

CONST
   rMenuBar = 128;
VAR
   menuBar:    Handle;
menuBar := GetNewMBar(rMenuBar); {read menus and menu bar }
                                  { descriptions,create & return }
                                  { a handle to a new menu list}
Use the SetMenuBar procedure to set the current menu list to the menu list created
by your application and the DrawMenuBar procedure to update the menu bar's appearance. For example, Listing 3-5 uses these two routines to set up the application's menu bar.

Listing 3-5 Setting up an application's menus and menu bar

PROCEDURE MyMakeMenus;   
VAR
   menuBar:                Handle;
 BEGIN                  
{first use the GetNewMBar function to read menus in & create a }
{ new menu list. If you define an Apple menu, the Menu Manager }
{ inserts the Help and Application menus (and Keyboard menu if }
{ necessary) into the newly created menu list}
   menuBar := GetNewMBar(rMenuBar);    
   IF menuBar = NIL THEN
      EXIT(MyMakeMenus);
   SetMenuBar(menuBar); {insert menus into the current menu list}
   DisposHandle(menuBar);
                        {add desktop items in Apple Menu Items }
                        { folder to Apple menu}
   AppendResMenu(GetMenuHandle(mApple), 'DRVR');
   MyAdjustMenus;       {adjust items and enabled state of menus}
   DrawMenuBar;         {draw the menu bar}
 END;
The code in Listing 3-5 creates the application's menu bar by reading in the definition from the 'MBAR' resource with resource ID 128, and it uses SetMenuBar to set the current menu list to the newly created menu list. The code then adds the desktop
items in the Apple Menu Items folder to the Apple menu using the AppendResMenu procedure.

You can use the GetMenuHandle function to get a handle to the menu record of
any menu in the current menu list. You supply the menu ID of the desired menu as a parameter to GetMenuHandle, and GetMenuHandle returns a handle to the menu's menu record. Most Menu Manager routines require either a menu ID or a handle to
a menu record as a parameter.

After creating the menu bar and adding any other menus or items as necessary, the code calls the MyAdjustMenus procedure to adjust the application's menus--for example, this procedure sets the enabled and disabled states of menu items in accordance with the current state of the application. (Listing 3-19 on page 3-76 shows the application-defined MyAdjustMenus procedure used in Listing 3-5.) After adjusting the menus, the code in Listing 3-5 uses DrawMenuBar to draw the menus in the menu bar according to their current enabled state and as they are defined in the current menu list.

Usually you'll define the menus of your application and its menu bar using 'MENU' resources and an 'MBAR' resource and using the GetNewMBar function to read the resource definitions. However, you can choose to read in a 'MENU' resource using the GetMenu function or to create a new empty menu using NewMenu. You can then insert
a menu into the current menu list using the InsertMenu procedure. See "Creating Menus" on page 3-105 and "Adding Menus to and Removing Menus From the Current Menu List" on page 3-108 for information on forming your menus using these routines.

If your application uses a submenu, you need to use the GetMenu function and InsertMenu procedure to make these menus available to your application. See "Creating a Hierarchical Menu" on page 3-55 for information on creating submenus.
If your application uses a pop-up menu, you can use the pop-up control definition function and Dialog Manager or Control Manager routines to create and display
the pop-up menu. See "Creating a Pop-Up Menu" on page 3-58 for information on creating pop-up menus.

The Menu Manager creates and initializes your application's menu color information table when your application calls GetNewMBar. You can add entries to your application's menu color information table if you want to use colors other than the default colors in your menus and menu bar. You can add entries to this table by providing menu color information table ('mctb') resources or by using the SetMCEntries procedure. Usually you should use the default colors to help maintain
a consistent user interface.

If you add menu color entries to your application's menu color information table and your application uses more than one menu bar, you need to save a copy of your application's menu color information table before changing menu bars. Use the GetMCInfo function before calling GetNewMBar and call SetMCInfo afterward to restore the menu color information table. Listing 3-6 shows a routine that saves and
then restores the menu color information table when creating a new menu bar.

Listing 3-6 Saving and restoring menu color information

PROCEDURE MyChangeMenuBarAndSaveColorInfo; 
CONST
   rMenuBar2 = 129;
VAR
   menu:                MenuHandle;
   menuBar:             Handle;
   currentMCTable:      MCTableHandle;
   newMCTable:          MCTableHandle;
 BEGIN
   currentMCTable := GetMCInfo;     {save menu color info table}
   IF currentMCTable = NIL THEN
      EXIT(MyChangeMenuBarAndSaveColorInfo);
   menuBar := GetNewMBar(rMenuBar2);{read menus in & create new menu list}
   IF menuBar = NIL THEN
      EXIT(MyChangeMenuBarAndSaveColorInfo);
   newMCTable := GetMCInfo;         {get new menu color info table} 
   IF newMCTable = NIL THEN
      EXIT(MyChangeMenuBarAndSaveColorInfo);
   SetMCInfo(currentMCTable);       {restore previous menu color info table}
   SetMenuBar(menuBar);             {insert menus into the current menu list}
   DisposHandle(menuBar);
   AppendResMenu(GetMenuHandle(m2Apple), 'DRVR'); {add desktop items from }
                                    { Apple Menu Items folder to Apple menu}
   MyAdjustMenus;                         {adjust menu items}
   DrawMenuBar;                           {draw the menu bar}
 END; 

Previous Book Contents Book Index Next

© Apple Computer, Inc.
11 JUL 1996