Demonstration Programs
Menus1
// ××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××
// Menus1.c
// ××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××
//
// This program:
//
// ¥ Opens a window.
//
// ¥ Creates these pull-down menus: Apple, File, Edit, Font, Style, Size, and Special.
//
// The Apple menu includes an "About..." menu item for the program.
//
// The second menu item in the Special menu contains a submenu.
//
// A "Help" menu item for the program is appended to the Help menu.
//
// ¥ Displays text in the window indicating the menu selection made by the user.
//
// The implementation of the Size menu is nominal only. The current size is indicated
// with a checkmark; however, the number of sizes shown is not font-dependent and there
// is no "Other" item.
//
// To facilitate a comparison with the fully theme-compliant menus in the
// demonstration program Menus2, no measures are taken in this program to cause the menu
// bar and menus to use the new menu bar and menu definition functions when system-wide
// Appearance is selected off in the Mac OS 8.0 and 8.1 Appearance control panel. The
// menu bar and menus will only use the new definition functions when system-wide
// Appearance is selected on in the Mac OS 8.0 and 8.1 Appearance control panel.
//
// Because the primary purpose of the program is to demonstrate menu creation and
// handling, no code is included to update and activate/deactivate the window or to
// respond to events which are not relevant to the demonstration.
//
// The program is terminated by selecting Quit from the File menu, by pressing the
// keyboard equivalent for that item (Command-Q), or by clicking in the window's go-away
// box.
//
// The program utilises the following resources:
//
// ¥ A 'WIND' resource (purgeable) (initially not visible).
//
// ¥ An 'MBAR' resource (preload, non-purgeable).
//
// ¥ 'MENU' resources for the drop-down and hierarchical menus (all preload, all
// non-purgeable).
//
//
// ××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××
// ............................................................................. includes
#include <Appearance.h>
#include <Balloons.h>
#include <Devices.h>
#include <Fonts.h>
#include <Sound.h>
#include <ToolUtils.h>
// .............................................................................. defines
#define mApple 128
#define iAbout 1
#define mFile 129
#define iQuit 11
#define mEdit 130
#define iUndo 1
#define iCut 3
#define iCopy 4
#define iPaste 5
#define iClear 6
#define mFont 131
#define mStyle 132
#define iPlain 1
#define iBold 3
#define iItalic 4
#define iUnderline 5
#define iOutline 6
#define iShadow 7
#define mSize 133
#define iTen 1
#define iTwelve 2
#define iEighteen 3
#define iTwentyFour 4
#define mSpecial 134
#define iFirstItem 1
#define iSecondItem 2
#define mSubmenu 135
#define iFirstSubItem 1
#define iSecondSubItem 2
#define rWindowResource 128
// ..................................................................... global variables
Boolean gDone;
SInt16 gCurrentFont = 1;
Style gCurrentStyle = 0;
SInt16 gCurrentSize = 2;
// .................................................................. function prototypes
void main (void);
void doInitManagers (void);
void doGetMenus (void);
void doEvents (EventRecord *);
void doMouseDown (EventRecord *);
void doAdjustMenus (void);
void doMenuChoice (SInt32);
void doAppleMenu (SInt16);
void doFileMenu (SInt16);
void doEditMenu (SInt16);
void doFontMenu (SInt16);
void doStyleMenu (SInt16);
void doSizeMenu (SInt16);
void doSpecialMenu (SInt16);
void doSubMenus (SInt16);
void doHelpMenu (SInt16);
void drawItemString (Str255);
// ××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××× main
void main(void)
{
EventRecord eventStructure;
WindowPtr windowPtr;
// ................................................................ initialise managers
doInitManagers();
// ...................................................................... open a window
if(!(windowPtr = GetNewCWindow(rWindowResource,NULL,(WindowPtr) -1)))
{
SysBeep(10);
ExitToShell();
}
SetPort(windowPtr);
// ........................................ set up menu bar and menus, then show window
doGetMenus();
ShowWindow(windowPtr);
// ......................................................................... event loop
gDone = false;
while(!gDone)
{
if(WaitNextEvent(everyEvent,&eventStructure,180,NULL))
doEvents(&eventStructure);
}
}
// ××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××× doInitManagers
void doInitManagers(void)
{
MaxApplZone();
MoreMasters();
InitGraf(&qd.thePort);
InitFonts();
InitWindows();
InitMenus();
TEInit();
InitDialogs(NULL);
InitCursor();
FlushEvents(everyEvent,0);
}
// ××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××× doGetMenus
void doGetMenus(void)
{
Handle menubarHdl;
MenuHandle menuHdl;
OSErr osErr;
menubarHdl = GetNewMBar(128);
if(menubarHdl == NULL)
ExitToShell();
SetMenuBar(menubarHdl);
DrawMenuBar();
menuHdl = GetMenuHandle(mApple);
if(menuHdl != NULL)
AppendResMenu(menuHdl,'DRVR');
else
ExitToShell();
menuHdl = GetMenuHandle(mFont);
if(menuHdl != NULL)
AppendResMenu(menuHdl,'FONT');
else
ExitToShell();
menuHdl = GetMenu(mSubmenu);
if(menuHdl != NULL)
InsertMenu(menuHdl,hierMenu);
else
ExitToShell();
osErr = HMGetHelpMenuHandle(&menuHdl);
if(osErr == noErr)
AppendMenu(menuHdl,"\pMenus1 Help");
else
ExitToShell();
doFontMenu(gCurrentFont);
doStyleMenu(gCurrentStyle);
doSizeMenu(gCurrentSize);
}
// ××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××× doEvents
void doEvents(EventRecord *eventStrucPtr)
{
SInt8 charCode;
switch(eventStrucPtr->what)
{
case mouseDown:
doMouseDown(eventStrucPtr);
break;
case keyDown:
case autoKey:
charCode = eventStrucPtr->message & charCodeMask;
if((eventStrucPtr->modifiers & cmdKey) != 0)
{
doAdjustMenus();
doMenuChoice(MenuEvent(eventStrucPtr));
}
break;
case updateEvt:
BeginUpdate((WindowPtr)eventStrucPtr->message);
EndUpdate((WindowPtr)eventStrucPtr->message);
break;
case osEvt:
HiliteMenu(0);
break;
}
}
// ×××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××× doMouseDown
void doMouseDown(EventRecord *eventStrucPtr)
{
WindowPtr windowPtr;
SInt16 partCode;
SInt32 menuChoice;
partCode = FindWindow(eventStrucPtr->where,&windowPtr);
switch(partCode)
{
case inMenuBar:
doAdjustMenus();
menuChoice = MenuSelect(eventStrucPtr->where);
doMenuChoice(menuChoice);
break;
case inContent:
if(windowPtr != FrontWindow())
SelectWindow(windowPtr);
break;
case inDrag:
DragWindow(windowPtr,eventStrucPtr->where,&qd.screenBits.bounds);
break;
case inGoAway:
if(TrackGoAway(windowPtr,eventStrucPtr->where))
gDone = true;
break;
}
}
// ×××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××× doAdjustMenus
void doAdjustMenus(void)
{
// Adjust menus here.
}
// ××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××× doMenuChoice
void doMenuChoice(SInt32 menuChoice)
{
SInt16 menuID, menuItem;
menuID = HiWord(menuChoice);
menuItem = LoWord(menuChoice);
if(menuID == 0)
return;
switch(menuID)
{
case mApple:
doAppleMenu(menuItem);
break;
case mFile:
doFileMenu(menuItem);
break;
case mEdit:
doEditMenu(menuItem);
break;
case mFont:
doFontMenu(menuItem);
break;
case mStyle:
doStyleMenu(menuItem);
break;
case mSize:
doSizeMenu(menuItem);
break;
case mSpecial:
doSpecialMenu(menuItem);
break;
case mSubmenu:
doSubMenus(menuItem);
break;
case kHMHelpMenuID:
doHelpMenu(menuItem);
break;
}
HiliteMenu(0);
}
// ×××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××× doAppleMenu
void doAppleMenu(SInt16 menuItem)
{
Str255 itemName;
SInt16 daDriverRefNum;
if(menuItem == iAbout)
drawItemString("\pAbout Menus1.");
else
{
GetMenuItemText(GetMenuHandle(mApple),menuItem,itemName);
daDriverRefNum = OpenDeskAcc(itemName);
}
}
// ××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××× doFileMenu
void doFileMenu(SInt16 menuItem)
{
if(menuItem == iQuit)
gDone = true;
}
// ××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××× doEditMenu
void doEditMenu(SInt16 menuItem)
{
switch(menuItem)
{
case iUndo:
drawItemString("\pUndo");
break;
case iCut:
drawItemString("\pCut");
break;
case iCopy:
drawItemString("\pCopy");
break;
case iPaste:
drawItemString("\pPaste");
break;
case iClear:
drawItemString("\pClear");
break;
}
}
// ××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××× doFontMenu
void doFontMenu(SInt16 menuItem)
{
MenuHandle fontMenuHdl;
Str255 fontName;
SInt16 fontNumber;
fontMenuHdl = GetMenuHandle(mFont);
CheckMenuItem(fontMenuHdl,gCurrentFont,false);
CheckMenuItem(fontMenuHdl,menuItem,true);
gCurrentFont = menuItem;
GetMenuItemText(fontMenuHdl,menuItem,fontName);
GetFNum(fontName,&fontNumber);
TextFont(fontNumber);
drawItemString(fontName);
}
// ×××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××× doStyleMenu
void doStyleMenu(SInt16 menuItem)
{
MenuHandle styleMenuHdl;
switch(menuItem)
{
case iPlain:
gCurrentStyle = 0;
break;
case iBold:
if(gCurrentStyle & bold)
gCurrentStyle -= bold;
else
gCurrentStyle |= bold;
break;
case iItalic:
if(gCurrentStyle & italic)
gCurrentStyle -= italic;
else
gCurrentStyle |= italic;
break;
case iUnderline:
if(gCurrentStyle & underline)
gCurrentStyle -= underline;
else
gCurrentStyle |= underline;
break;
case iOutline:
if(gCurrentStyle & outline)
gCurrentStyle -= outline;
else
gCurrentStyle |= outline;
break;
case iShadow:
if(gCurrentStyle & shadow)
gCurrentStyle -= shadow;
else
gCurrentStyle |= shadow;
break;
}
styleMenuHdl = GetMenuHandle(mStyle);
CheckMenuItem(styleMenuHdl,iPlain, gCurrentStyle == 0);
CheckMenuItem(styleMenuHdl,iBold, gCurrentStyle & bold);
CheckMenuItem(styleMenuHdl,iItalic, gCurrentStyle & italic);
CheckMenuItem(styleMenuHdl,iUnderline, gCurrentStyle & underline);
CheckMenuItem(styleMenuHdl,iOutline, gCurrentStyle & outline);
CheckMenuItem(styleMenuHdl,iShadow, gCurrentStyle & shadow);
TextFace(gCurrentStyle);
drawItemString("\pStyle change");
}
// ××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××× doSizeMenu
void doSizeMenu(SInt16 menuItem)
{
MenuHandle sizeMenuHdl;
switch(menuItem)
{
case iTen:
TextSize(10);
break;
case iTwelve:
TextSize(12);
break;
case iEighteen:
TextSize(18);
break;
case iTwentyFour:
TextSize(24);
break;
}
sizeMenuHdl = GetMenuHandle(mSize);
CheckMenuItem(sizeMenuHdl,gCurrentSize,false);
CheckMenuItem(sizeMenuHdl,menuItem,true);
gCurrentSize = menuItem;
drawItemString("\pSize change");
}
// ×××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××× doSpecialMenu
void doSpecialMenu(SInt16 menuItem)
{
if(menuItem == iFirstItem)
drawItemString("\pFirst Item");
}
// ××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××× doSubMenus
void doSubMenus(SInt16 menuItem)
{
switch(menuItem)
{
case iFirstSubItem:
drawItemString("\pSubitem 1");
break;
case iSecondSubItem:
drawItemString("\pSubitem 2");
break;
}
}
// ××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××× doHelpMenu
void doHelpMenu(SInt16 menuItem)
{
MenuHandle helpMenuHdl;
SInt16 origHelpItems, numItems;
HMGetHelpMenuHandle(&helpMenuHdl);
numItems = CountMenuItems(helpMenuHdl);
origHelpItems = numItems - 1;
if(menuItem > origHelpItems)
drawItemString("\pMenus1 Help");
}
// ××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××× drawItemString
void drawItemString(Str255 eventString)
{
RgnHandle tempRegion;
WindowPtr windowPtr;
Rect scrollBox;
windowPtr = FrontWindow();
tempRegion = NewRgn();
scrollBox = windowPtr->portRect;
ScrollRect(&scrollBox,0,-24,tempRegion);
DisposeRgn(tempRegion);
MoveTo(8,286);
DrawString(eventString);
}
// ××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××
Menus2
// ××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××
// Menus2.c
// ××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××
//
// This program is based on Menus1 and, amongst other things, demonstrates:
//
// ¥ How to achieve theme-compliant menus and menu bars.
//
// ¥ The additional menus-related features introduced with Mac OS 8 and the Appearance
// Manager and, later, Mac OS 8.5.
//
// The basic differences between this program and Menus1 are as follows:
//
// ¥ A call to RegisterAppearanceClient is used early in main() to cause the new menu
// bar definition function (resource ID 63) to be used regardless of whether
// system-wide Appearance is selected on or off in the Mac OS 8.0 and 8.1 Appearance
// control panel. Also, the new menu definition function (resource ID 63) is
// specified in the 'MENU' resource for all menus, meaning that that that definition
// function will be used regardless of whether system-wide Appearance is selected on
// or off in the Mac OS 8.0 and 8.1 Appearance control panel.
//
// ¥ 'xmnu' resources are used to extend the 'MENU' resources for all non-system
// managed menus and the Font menu.
//
// ¥ Extended modifier keys (Shift, Option, and Control) are used to extend the
// Command-key equivalents for two menu items in the Style menus.
//
// ¥ There are two Style menus (Style ('xmnu') and Style (Programmatic). The two Style
// menus are intended to demonstrate an anomaly in the first version of the
// theme-compliant menu definition function (resource ID 63) in the case where
// extended modifier keys are assigned to a menu item via an 'xmnu' resource as
// opposed to being assigned programmatically. (Note that this only applies to Mac
// OS 8.0 and 8.1. This problem was fixed in Mac OS 8.5.)
//
// ¥ Command IDs are assigned to all menu items except those in the system-managed
// menus and the Font menu, and the associated menu handling code branches according
// to the command ID of the chosen menu item (as opposed to menu ID and menu item).
//
// ¥ The Font menu is WYSIWYG, meaning that each item is drawn in that font.
//
// ¥ The delete-to-the-left, delete-to-the-right, page-up, and page-down keys are
// assigned as Command-key equivalents in the Size menu, and the glyphs are adjusted
// where necessary.
//
// ¥ If Mac OS 8.5 is present, the mark column is eliminated from the Special menu and
// the font for the menu is set to the Gadget font (if it is present).
//
// ¥ The submenu is attached to the second item in the Special menu programmatically
// rather than via the 'MENU' resource.
//
// ¥ Colour icons are included in the menu items in the submenu.
//
// ¥ Balloon help is provided, via 'hmnu' resources, for all menus.
//
// ¥ A Menus2 Help item is not programmatically appended to the Help Menu. Instead, an
// Apple Guide file, which is included in the application folder, causes the system
// to install a Menus Help item in the Help menu. (Note: This works only when the
// application is run on Mac OS 8.6 and later.)
//
// The extended modifier keys in the Style ('xmnu') menu are assigned via the 'xmnu'
// resource for that menu. The extended modifier keys in the Style (Programmatic)
// menu are assigned programmatically via calls to SetMenuItemModifiers.
//
// The command IDs for items in the File, Edit, and Style ('xmnu') menus are assigned via
// the 'xmnu' resources for those menus. The command IDs for the items in the Style
// (Programmatic), Size, and Special menus, and the submenu, are assigned
// programmatically.
//
// The colour icon in the first submenu item is assigned via the 'MENU' resource. The
// colour icon in the second item is assigned programmatically via a call to
// SetMenuItemIconHandle.
//
// The program utilises the following resources:
//
// ¥ A 'WIND' resource (purgeable) (initially not visible).
//
// ¥ An 'MBAR' resource (preload, non-purgeable).
//
// ¥ 'MENU' resources for the drop-down menus and submenu (all preload, all non-
// purgeable).
//
// ¥ 'xmnu' resources (preload, purgeable) for the drop-down menus (except the
// system-managed menus and the Font menu) and the submenu.
//
// ¥ 'hmnu' resources (purgeable) providing balloon help for menus and menu items.
//
// ¥ Two 'cicn' resources (purgeable) for the items in the submenu.
//
// ××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××
// ............................................................................. includes
#include <Appearance.h>
#include <Devices.h>
#include <Fonts.h>
#include <Gestalt.h>
#include <Sound.h>
#include <ToolUtils.h>
// .............................................................................. defines
#define mApple 128
#define iAbout 1
#define mFile 129
#define idQuit 'quit'
#define mEdit 130
#define idUndo 'undo'
#define idCut 'cut '
#define idCopy 'copy'
#define idPaste 'past'
#define idClear 'clea'
#define mFont 131
#define mStyle_xmnu 132
#define idPlain_xmnu 'plax'
#define idBold_xmnu 'bolx'
#define idItalic_xmnu 'itax'
#define idUnderline_xmnu 'undx'
#define idOutline_xmnu 'outx'
#define idShadow_xmnu 'shax'
#define mStyle_prog 133
#define iPlain 1
#define iBold 3
#define iItalic 4
#define iOutline 6
#define iUnderline 5
#define iShadow 7
#define idPlain_prog 'plap'
#define idBold_prog 'bolp'
#define idItalic_prog 'itap'
#define idUnderline_prog 'undp'
#define idOutline_prog 'outp'
#define idShadow_prog 'shap'
#define mSize 134
#define iTen 1
#define iTwelve 2
#define iEighteen 3
#define iTwentyFour 4
#define idTen 'ten '
#define idTwelve 'twel'
#define idEighteen 'eigh'
#define idTwentyFour 'twen'
#define mSpecial 135
#define iFirst 1
#define iSecond 2
#define idFirst 'firs'
#define mSubmenu 136
#define iBat 1
#define iBowl 2
#define idBat 'bat '
#define idBowl 'bowl'
#define rWindowResource 128
#define rColourIcon 258
// ..................................................................... global variables
Boolean gMacOS_85_present;
Boolean gDone;
SInt16 gCurrentFont = 1;
Style gCurrentStyle = 0;
SInt16 gCurrentSize = 2;
// .................................................................. function prototypes
void main (void);
void doInitManagers (void);
void doGetMenus (void);
void doEvents (EventRecord *);
void doMouseDown (EventRecord *);
void doAdjustMenus (void);
void doMenuChoice (SInt32);
void doAppleMenu (SInt16);
void doFontMenu (SInt16);
void doCheckStyleMenuItem (SInt16);
void doCheckSizeMenuItem (SInt16,SInt16);
void drawItemString (Str255);
// ××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××× main
void main(void)
{
SInt32 response;
EventRecord eventStructure;
WindowPtr windowPtr;
RGBColor foreColour = { 0xFFFF,0xFFFF,0xFFFF };
RGBColor backColour = { 0x4444,0x4444,0x9999 };
// ................................................................ initialise managers
doInitManagers();
// ....... cause the theme-compliant menu bar definition function to be called directly
RegisterAppearanceClient();
// ............................................ check if Mac OS 8.5 or later is present
Gestalt(gestaltSystemVersion,&response);
if(response >= 0x00000850)
gMacOS_85_present = true;
else
gMacOS_85_present = false;
// ...................................................................... open a window
if(!(windowPtr = GetNewCWindow(rWindowResource,NULL,(WindowPtr) -1)))
{
SysBeep(10);
ExitToShell();
}
SetPort(windowPtr);
TextFace(bold);
RGBBackColor(&backColour);
RGBForeColor(&foreColour);
// ........................................ set up menu bar and menus, then show window
doGetMenus();
ShowWindow(windowPtr);
EraseRect(&windowPtr->portRect);
// ......................................................................... event loop
gDone = false;
while(!gDone)
{
if(WaitNextEvent(everyEvent,&eventStructure,180,NULL))
doEvents(&eventStructure);
}
}
// ××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××× doInitManagers
void doInitManagers(void)
{
MaxApplZone();
MoreMasters();
InitGraf(&qd.thePort);
InitFonts();
InitWindows();
InitMenus();
TEInit();
InitDialogs(NULL);
InitCursor();
FlushEvents(everyEvent,0);
}
// ××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××× doGetMenus
void doGetMenus(void)
{
Handle menubarHdl;
MenuHandle menuHdl;
SInt16 a, numberOfItems, fontNumber;
Str255 fontName;
CIconHandle cicnHdl;
// .............................................................. get and draw menu bar
menubarHdl = GetNewMBar(128);
if(menubarHdl == NULL)
ExitToShell();
SetMenuBar(menubarHdl);
DrawMenuBar();
// .................................................................. set up Apple menu
menuHdl = GetMenuHandle(mApple);
if(menuHdl != NULL)
AppendResMenu(menuHdl,'DRVR');
else
ExitToShell();
// .................................................. set up Font menu and make WYSIWYG
menuHdl = GetMenuHandle(mFont);
if(menuHdl != NULL)
{
AppendResMenu(menuHdl,'FONT');
numberOfItems = CountMenuItems(menuHdl);
for(a=1;a<=numberOfItems;a++)
{
GetMenuItemText(menuHdl,a,fontName);
GetFNum(fontName,&fontNumber);
SetMenuItemFontID(menuHdl,a,fontNumber);
}
}
else
ExitToShell();
// ........... programmatically set the extended modifiers in Style (Programmatic) menu
menuHdl = GetMenuHandle(mStyle_prog);
SetMenuItemModifiers(menuHdl,iOutline,kMenuShiftModifier + kMenuOptionModifier
+ kMenuControlModifier);
SetMenuItemModifiers(menuHdl,iShadow,kMenuShiftModifier + kMenuOptionModifier);
//Êinsert submenu into menu list and programmatically attach it to Special menu, item 2
menuHdl = GetMenu(mSubmenu);
if(menuHdl != NULL)
{
InsertMenu(menuHdl,hierMenu);
menuHdl = GetMenuHandle(mSpecial);
SetMenuItemHierarchicalID(menuHdl,iSecond,mSubmenu);
}
else
ExitToShell();
// . programmatically set command IDs for second Style, Size, Special menus and submenu
menuHdl = GetMenuHandle(mStyle_prog);
SetMenuItemCommandID(menuHdl,iPlain, idPlain_prog);
SetMenuItemCommandID(menuHdl,iBold, idBold_prog);
SetMenuItemCommandID(menuHdl,iItalic, idItalic_prog);
SetMenuItemCommandID(menuHdl,iUnderline, idUnderline_prog);
SetMenuItemCommandID(menuHdl,iOutline, idOutline_prog);
SetMenuItemCommandID(menuHdl,iShadow, idShadow_prog);
menuHdl = GetMenuHandle(mSize);
SetMenuItemCommandID(menuHdl,iTen, idTen);
SetMenuItemCommandID(menuHdl,iTwelve, idTwelve);
SetMenuItemCommandID(menuHdl,iEighteen, idEighteen);
SetMenuItemCommandID(menuHdl,iTwentyFour, idTwentyFour);
menuHdl = GetMenuHandle(mSpecial);
SetMenuItemCommandID(menuHdl,iFirst, idFirst);
menuHdl = GetMenuHandle(mSubmenu);
SetMenuItemCommandID(menuHdl,iBat, idBat);
SetMenuItemCommandID(menuHdl,iBowl, idBowl);
// ..................... programmatically set the icon for the Bowl item in the submenu
cicnHdl = GetCIcon(rColourIcon);
SetMenuItemIconHandle(menuHdl,iBowl,kMenuColorIconType,(Handle) cicnHdl);
// .. programmatically set Command-key equivalents to Size menu items and adjust glyphs
menuHdl = GetMenuHandle(mSize);
SetItemCmd(menuHdl,iTen,0x08);
SetMenuItemKeyGlyph(menuHdl,iTen,0x17);
SetItemCmd(menuHdl,iTwelve,0x7f);
SetMenuItemKeyGlyph(menuHdl,iTwelve,0x0A);
SetItemCmd(menuHdl,iEighteen,0x0b);
SetItemCmd(menuHdl,iTwentyFour,0x0c);
// ...... programmatically exclude the mark column and set the font in the Special menu
#if TARGET_CPU_PPC
if(gMacOS_85_present)
{
menuHdl = GetMenuHandle(mSpecial);
SetMenuExcludesMarkColumn(menuHdl,true);
GetFNum("\pGadget",&fontNumber);
if(fontNumber != 0)
SetMenuFont(menuHdl,fontNumber,12);
}
#endif
// .............................. set initial font, style, and size, and checkmark them
doFontMenu(gCurrentFont);
doCheckStyleMenuItem(mStyle_xmnu);
doCheckStyleMenuItem(mStyle_prog);
doCheckSizeMenuItem(mSize,iTen);
}
// ××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××× doEvents
void doEvents(EventRecord *eventStrucPtr)
{
SInt8 charCode;
switch(eventStrucPtr->what)
{
case mouseDown:
doMouseDown(eventStrucPtr);
break;
case keyDown:
case autoKey:
charCode = eventStrucPtr->message & charCodeMask;
if((eventStrucPtr->modifiers & cmdKey) != 0)
{
doAdjustMenus();
doMenuChoice(MenuEvent(eventStrucPtr));
}
break;
case updateEvt:
BeginUpdate((WindowPtr)eventStrucPtr->message);
EndUpdate((WindowPtr)eventStrucPtr->message);
break;
case osEvt:
HiliteMenu(0);
break;
}
}
// ×××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××× doMouseDown
void doMouseDown(EventRecord *eventStrucPtr)
{
WindowPtr windowPtr;
SInt16 partCode;
SInt32 menuChoice;
partCode = FindWindow(eventStrucPtr->where,&windowPtr);
switch(partCode)
{
case inMenuBar:
doAdjustMenus();
menuChoice = MenuSelect(eventStrucPtr->where);
doMenuChoice(menuChoice);
break;
case inContent:
if(windowPtr != FrontWindow())
SelectWindow(windowPtr);
break;
case inDrag:
DragWindow(windowPtr,eventStrucPtr->where,&qd.screenBits.bounds);
break;
case inGoAway:
if(TrackGoAway(windowPtr,eventStrucPtr->where))
gDone = true;
break;
}
}
// ×××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××× doAdjustMenus
void doAdjustMenus(void)
{
// Adjust menus here.
}
// ××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××× doMenuChoice
void doMenuChoice(SInt32 menuChoice)
{
SInt16 menuID, menuItem;
OSErr osErr;
UInt32 commandID;
MenuHandle menuHdl;
menuID = HiWord(menuChoice);
menuItem = LoWord(menuChoice);
if(menuID == 0)
return;
if(menuID == mApple)
doAppleMenu(menuItem);
else if(menuID == mFont)
doFontMenu(menuItem);
else
{
osErr = GetMenuItemCommandID(GetMenuHandle(menuID),menuItem,&commandID);
if(osErr || commandID != 0)
{
switch(commandID)
{
// .................................................................... File menu
case 'quit':
gDone = true;
break;
// .................................................................... Edit menu
case 'undo':
drawItemString("\pUndo");
break;
case 'cut ':
drawItemString("\pCut");
break;
case 'copy':
drawItemString("\pCopy");
break;
case 'past':
drawItemString("\pPaste");
break;
case 'clea':
drawItemString("\pClear");
break;
// ................................. Style ('xmnu') and Style (Programmatic) menu
case 'plax':
case 'plap':
gCurrentStyle = 0;
doCheckStyleMenuItem(menuID);
break;
case 'bolx':
case 'bolp':
if(gCurrentStyle & bold)
gCurrentStyle -= bold;
else
gCurrentStyle |= bold;
doCheckStyleMenuItem(menuID);
break;
case 'itax':
case 'itap':
if(gCurrentStyle & italic)
gCurrentStyle -= italic;
else
gCurrentStyle |= italic;
doCheckStyleMenuItem(menuID);
break;
case 'undx':
case 'undp':
if(gCurrentStyle & underline)
gCurrentStyle -= underline;
else
gCurrentStyle |= underline;
doCheckStyleMenuItem(menuID);
break;
case 'outx':
case 'outp':
if(gCurrentStyle & outline)
gCurrentStyle -= outline;
else
gCurrentStyle |= outline;
doCheckStyleMenuItem(menuID);
break;
case 'shax':
case 'shap':
if(gCurrentStyle & shadow)
gCurrentStyle -= shadow;
else
gCurrentStyle |= shadow;
doCheckStyleMenuItem(menuID);
break;
// .................................................................... Size menu
case 'ten ':
TextSize(10);
doCheckSizeMenuItem(menuID,menuItem);
break;
case 'twel':
TextSize(12);
doCheckSizeMenuItem(menuID,menuItem);
break;
case 'eigh':
TextSize(18);
doCheckSizeMenuItem(menuID,menuItem);
break;
case 'twen':
TextSize(24);
doCheckSizeMenuItem(menuID,menuItem);
break;
// ................................................................. Special menu
case 'firs':
drawItemString("\pFirst Item");
break;
// ...................................................................... submenu
case 'bat ':
menuHdl = GetMenuHandle(mSubmenu);
DisableItem(menuHdl,iBat);
EnableItem(menuHdl,iBowl);
drawItemString("\pBat");
break;
case 'bowl':
menuHdl = GetMenuHandle(mSubmenu);
DisableItem(menuHdl,iBowl);
EnableItem(menuHdl,iBat);
drawItemString("\pBowl");
break;
}
}
}
HiliteMenu(0);
}
// ×××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××× doAppleMenu
void doAppleMenu(SInt16 menuItem)
{
Str255 itemName;
SInt16 daDriverRefNum;
if(menuItem == iAbout)
drawItemString("\pAbout Menus2.");
else
{
GetMenuItemText(GetMenuHandle(mApple),menuItem,itemName);
daDriverRefNum = OpenDeskAcc(itemName);
}
}
// ××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××× doFontMenu
void doFontMenu(SInt16 menuItem)
{
MenuHandle fontMenuHdl;
Str255 fontName;
SInt16 fontNumber;
fontMenuHdl = GetMenuHandle(mFont);
CheckMenuItem(fontMenuHdl,gCurrentFont,false);
CheckMenuItem(fontMenuHdl,menuItem,true);
gCurrentFont = menuItem;
GetMenuItemText(fontMenuHdl,menuItem,fontName);
GetFNum(fontName,&fontNumber);
TextFont(fontNumber);
drawItemString(fontName);
}
// ××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××× doCheckStyleMenuItem
void doCheckStyleMenuItem(SInt16 menuID)
{
MenuHandle styleMenuHdl;
styleMenuHdl = GetMenuHandle(menuID);
CheckMenuItem(styleMenuHdl,iPlain, gCurrentStyle == 0);
CheckMenuItem(styleMenuHdl,iBold, gCurrentStyle & bold);
CheckMenuItem(styleMenuHdl,iItalic, gCurrentStyle & italic);
CheckMenuItem(styleMenuHdl,iUnderline,gCurrentStyle & underline);
CheckMenuItem(styleMenuHdl,iOutline, gCurrentStyle & outline);
CheckMenuItem(styleMenuHdl,iShadow, gCurrentStyle & shadow);
TextFace(gCurrentStyle);
drawItemString("\pStyle change");
}
// ×××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××× doCheckSizeMenuItem
void doCheckSizeMenuItem(SInt16 menuID,SInt16 menuItem)
{
MenuHandle sizeMenuHdl;
sizeMenuHdl = GetMenuHandle(menuID);
CheckMenuItem(sizeMenuHdl,gCurrentSize,false);
CheckMenuItem(sizeMenuHdl,menuItem,true);
gCurrentSize = menuItem;
drawItemString("\pSize change");
}
// ××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××× drawItemString
void drawItemString(Str255 eventString)
{
RgnHandle tempRegion;
WindowPtr windowPtr;
Rect scrollBox;
windowPtr = FrontWindow();
tempRegion = NewRgn();
scrollBox = windowPtr->portRect;
ScrollRect(&scrollBox,0,-30,tempRegion);
DisposeRgn(tempRegion);
MoveTo(8,286);
DrawString(eventString);
}
// ××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××
Demonstration Program Comments
Menus1
When this program is run, the user should make menu selections from all menus, including
the Apple menu and the Help menu. Selections should be made using the mouse and, where
appropriate, the Command key equivalents. The user should also note the effects on the
menu bar of clicking outside, then inside, the program's window, that is, of sending the
program to the background and returning it to the foreground.
#define
Constants are established for the pull-down and hierarchical menu IDs and resources, menu
item numbers and subitem numbers. The last line establishes a constant for the resource
ID of the 'WIND' resource.
Global Variables
The global variable gDone relates to the main event loop. When set to true, the loop
will exit and the program will terminate. The remaining three global variables will hold
the current choices, in terms of item numbers, from the Font, Style and Size menus.
main
The main() function initialises the system software managers, creates a window and makes
its graphics port the current port, calls the application-defined function which sets up
the menus, shows the window and enters the main event loop.
doGetMenus
doGetMenus sets up the menu bar and the various menus.
At the first block, GetNewMBar reads in the 'MENU' resources for each menu specified in
the 'MBAR' resource and creates a menu record for each of those menus. (Note that the
error handling here and in other areas of this program is somewhat rudimentary: the
program simply terminates.) The call to SetMenuBar makes the newly created menu list the
current list and DrawMenuBar draws the menu bar.
The next block adds the contents of the Apple Menu Items folder to the Apple menu. The
use of 'DRVR' as the second parameter to the AppendResMenu call is automatically
interpreted to mean that the Apple menu is being created, so that all items in the Apple
Menu Items folder are added rather than resources of type 'DRVR'.
The third block adds the names of all resident fonts to the Font menu. Using 'FONT' in
the second parameter in the call to AppendResMenu causes all such resources to be
searched out and their names added to the specified menu.
The fourth block inserts the application's single submenu into the submenu portion of the
menu list. GetNewMBar does not read in the resource descriptions of submenus, so the
first step is to read in the 'MENU' resource with GetMenu. InsertMenu inserts a menu
record for this menu into the menu list at the location specified in the second parameter
to this call. Using the constant hierMenu (-1) as the second parameter causes the menu
to be installed in the submenu portion of the menu list.
The next block appends a menu item with the name "Menus Help" to the Help menu.
The last three lines cause checkmarks to be set against the appropriate font, style and
size menu items according to the initialised values of the associated global
variables.
doEvents
doEvents switches according to the type of low-level or Operating System event received.
Further processing is called for in the case of mouse-down or Command key equivalents,
these being central to the matter of menu handling.
In the case of key-down and auto-key events, the character code is first extracted from
the event record's message field. A check is then made of the modifiers field to
establish whether the Command key was also pressed at the time. If so, menu
enabling/disabling is attended to before the call to MenuEvent establishes whether the
character code is associated with a currently enabled menu or submenu item in the menu
list. If a match is found, MenuEvent returns a long integer containing the menu ID in
the high word and the item number in the low word, otherwise it returns 0 in the high
word. This long integer is then passed to the function doMenuChoice.
The call to HiliteMenu at the osEvt case unhighlights the Apple menu title when the user
brings the demonstration program to the foreground, having previously sent it to the
background by choosing an Apple Menu Items folder item from the Apple menu.
doMouseDown
doMouseDown first establishes the window and window part in which the mouse-down event
occurred, and switches accordingly. This demonstration program is specifically concerned
with mouse-downs in the menu bar and the content region of the window.
If the event occurred in this program's menu bar, menu enabling/disabling is attended to
before the call to MenuSelect. MenuSelect tracks the user's actions until the mouse
button is released, at which time it returns a long integer. If the user actually chose
a menu item, this long integer contains the menu ID in the high word and the item number
in the low word, otherwise it contains 0 in the high word. This long integer is passed
to the function doMenuChoice.
If the mouse-down event occurred in the content region of the window, and if the window
to which the mouse-down refers is not the front window, SelectWindow is called to effect
basic window activation/deactivation.
The inDrag case responds to a mouse-down in the drag bar.
The inGoAway case responds to a mouse-down in the go-away box, setting gDone to true and
thus terminating the program if the cursor is still within the go-away box when the mouse
button is released.
doAdjustMenus
doAdjustMenus is called when a mouse-down occurs in the menu bar and when examination of
a key-down event reveals that a menu item's keyboard equivalent has been pressed. No
action is taken in this simple program because only one window, whose content never
changes, is ever open.
(Later demonstration programs contain examples of menu adjustment functions which cater
for specific circumstances. For example, the menu adjustment function in the
demonstration program at Chapter 8 - Dialogs and Alerts accommodates the situation where
the front window could be either a document window or a modeless dialog box.)
doMenuChoice
doMenuChoice takes the long integer returned by the MenuSelect and MenuEvent calls,
extracts the high word (the menu ID) and the low word (the menu item number) and switches
according to the menu ID.
At the first two lines, the menu ID and the menu item number are extracted from the long
integer. The next two lines will cause an immediate return if the high word equals 0,
(meaning that either the mouse button was released when the pointer was outside the menu
box or MenuEvent found no menu list match for the key pressed in conjunction with the
Command key).
Within the switch on the menu ID, the appropriate application-defined individual menu
handling function are called. Note the handling of the hierarchical menu (case
mSubMenu). Note also that, at the last case, the kHMHelpMenuID constant (-16490) is
returned in the high word if the user chooses an appended item from the Help menu.
MenuEvent and MenuSelect leave the menu title highlighted if an item was actually
selected. Accordingly, the last line unhighlights the menu title when the action
associated with the user's drop-down menu choice is complete.
doAppleMenu
doAppleMenu takes the short integer representing the menu item. If this value represents
the first item in the Apple menu (the inserted "About..." item), text representing this
item is drawn in the scrolling display.
If the value passed to the doAppleMenu function represents other items in the Apple menu,
the call to GetMenuItemText gets the string representing the item's name. This string
(which excludes metacharacters) is used as the parameter in the OpenDeskAcc call.
OpenDeskAcc opens the chosen object and passes control that object.
doFileMenu
doFileMenu handles choices from the File menu. In this demonstration, only the Quit item
is enabled, all other items having been disabled in the File menu's 'MENU' resource.
When this item is chosen, the global variable gDone is set to true, causing termination
of the program.
doEditMenu
doEditMenu switches according to the menu item number, drawing text representing the
chosen item in the window.
doFontMenu
doFontMenu first gets a handle to the Font menu structure required by the following
CheckMenuItem calls. The CheckMenuItem calls uncheck the current font menu item and
check the menu item passed to the doFontMenu function. This latter menu item number is
then assigned to the gCurrentFont global variable.
The call to GetMenuItemText extracts the string representing the item's name. This
string is passed as the first parameter in the call to GetFNum, which gets the font
number associated with the name. This number is then used in the call to TextFont, which
will cause subsequent text drawing to be conducted in the specified font. The last line
draws the name of the font in that font.
doStyleMenu
doStyleMenu switches according to the menu item chosen in the Style menu. Within the
switch, bits in the global variable gCurrentStyle are set or unset according to the font
styles selected. The code reflects the fact that Bold, Italic, Underline, Outline and
Shadow style selections are additive, not mutually exclusive, and that a selection of
Plain must unset all bits in gCurrentStyle. The code also reflects the requirement that,
except in the case of the Plain item, the selection of a checked item must cause that
item to be unchecked, and vice versa.
With the appropriate bit settings of gCurrentStyle attended to, a handle to the Style
menu record is then obtained. This is required for the six CheckMenuItem, which check or
uncheck the individual menu items according to whether the third argument evaluates to,
respectively, true or false.
The call to TextFace sets the style for subsequent text drawing. The last line draws
some text to prove that the desired effect was achieved.
doSizeMenu
doSizeMenu switches according to the menu item chosen in the Size menu, sets the text
size for all text drawing to that size, unchecks the current size item, and checks the
newly chosen item. gCurrentSize is then set to the selected menu item number before the
function returns.
doSpecialMenu
doSpecialMenu handles a choice of the first item in the Special menu. Since the second
item is the title of a submenu, only the first item is attended to in this
function.
doSubMenus
doSubMenus switches according to the chosen subitem in the hierarchical menu represented
by the second menu item in the Special menu.
doHelpMenu
doHelpMenu handles the choice of the "Menus Help" item added by this program to the
system-managed Help Menu. This code reflects the fact that Apple reserves the right to
add items to the Help menu in future versions of the system software.
HMGetHelpMenuHandle gets a handle to the Help menu record. The call to CountMenuItems
returns the number of items in the Help menu. Since we know that we have added one item
to this menu, the next line will establish the original number of help items. If the
value passed to the doHelpMenu function is greater than this number, it must therefore
represent the item number of our "Menus Help" item, in which case some text is drawn in
the window to register the fact.
drawItemString
The function drawItemString is incidental to the demonstration, being called by the menu
selection handling functions to draw text in the application's window to reflect the
user's menu choices.
![](images/ruler.gif)
Menus2
This demonstration program includes a demonstration of Apple Help, including
the methodology used to create an item in the Help menu. The Apple Guide file titled
"Menus Guide", which will cause a "Menus Help" item to be created in the Help menu,
should be retained in the same folder as the Menus2 application. The folder titled
"Menus Help" should be moved to the Help folder in the System Folder. You will then
be able to access the help content by choosing Menus Help from the Help menu.
The help content does not provide user assistance for the Menus2 programs as such.
Rather, it provides a brief description of how to provide user assistance for your
application using Apple Help.
Note that Apple Help is only available on Mac OS 8.6 and later.
|
When this program is run, the user should choose Show Balloons from the Help menu and
make menu selections from all menus, including the Apple menu and the Help menu.
Selections should be made using the mouse and, where appropriate, the keyboard
equivalents. The user should also note:
* That, if the program is being run under Mac OS 8.0 or 8.1, the appearance of the
menu bar and menus remains the same regardless of whether system-wide appearance
is selected on or off in the Mac OS 8.0 and 8.1 Appearance control panel.
* The extended modifier keys assigned to the last two items in the Style menus.
* The Command-key equivalents assigned to the items in the Size menu. (These are,
in order, delete-to-the-left key, delete-to-the-right key, page-up key, and
page-down key.)
* That the Font menu is WYSIWYG.
* That, if the program is compiled and run under Mac OS 8.5, the marking character
column has been deleted from the Special menu and the menu items in this menu are
drawn in the Gadget font (assuming it is available).* That the items in the
submenu attached to the second item in the Special menu
have colour icons.
* That, if the program is being run under Mac OS 8.0 or 8.1, there is an anomaly in
the way the new MDEF draws Style menus. In the Style ('xmnu') menu, in which the
extended modifier keys for the last two menu items are assigned via the 'xmnu'
resource, the item text is severely truncated and an ellipsis is added. In the
Style (Programmatic) menu, in which the extended modifier keys are assigned
programmatically, this truncation of the item text does not occur. (This problem
was fixed in Mac OS 8.5.)
* The balloon help provided for all menus and menu items.
Because this demonstration program is based on Menus1, the following comments exclude
those for application-defined functions remain unchanged.
#define
The #defines now establish constants for command IDs for menu items. Command IDs are of
type UInt32. To enhance source code readability, these are defined in the
four-character-code format, which packs four one-byte characters together in a 32-bit
value.
main
The call to RegisterAppearanceClient means that the new theme-compliant menu
bar
definition function (resource ID 63) will be used regardless of whether system-wide
Appearance is selected on or off in the Mac OS 8.0 and 8.1 Appearance control panel.
Next, the function Gestalt is used to determine whether Mac OS 8.5 or later is present.
If so, the global variable gMacOS_85_present is set to true. (In the function
doGetMenus, this global variable will determine whether two functions introduced with
Mac OS 8.5 get called.)
The calls to RGBBackColor and RGBForeColor set the window background and foreground
colours to, respectively, dark blue and white.
doGetMenus
doGetMenus sets up the menu bar and the various menus.
GetNewMBar reads in the 'MENU' resources for each menu specified in the 'MBAR' resource
and creates a menu structure for each of those menus. (Note that the error handling here
and in other areas of this program is somewhat rudimentary: the program simply
terminates.) SetMenuBar makes the newly created menu list the current list and
DrawMenuBar draws the menu bar.
The next block adds the contents of the Apple Menu Items folder to the Apple menu. The
use of 'DRVR' as the second parameter to the AppendResMenu call is automatically
interpreted to mean that the Apple menu is being created, so that all items in the Apple
Menu Items folder are added rather than resources of type 'DRVR'.
The next block adds the names of all resident fonts to the Font menu and makes the menu
WYSIWYG. The call to AppendResMenu causes all 'FONT' resources to be searched out and
their names added to the specified menu. The process of making the menu WYSIWYG then
begins. The call to CountMenuItems returns the number of items in the menu. Then, for
each of these items, GetMenuItemText gets the text (the font's name), GetFNum gets the
font number associated with the font name, and SetMenuItemFontID sets the font for the
menu item.
The next block programmatically assigns extended modifier keys to the Outline and Shadow
items in the Style (Programmatic) menu. The SetMenuItemModifiers calls assign
Shift-Option-Control to the Outline item and Shift-Option to the Shadow item. (The
extended modifier keys for the same two items in the Style ('xmnu') menu are assigned in
the associated 'xmnu' resources.
The next block inserts the application's single submenu into the submenu portion of the
menu list and programmatically attaches it to the Special menu's second menu item.
GetNewMBar does not read in the resource descriptions of submenus, so the first step is
to read in the 'MENU' resource with GetMenu. InsertMenu inserts a menu structure for
this menu into the menu list at the location specified in the second parameter to this
call. (Using the constant hierMenu (-1) as the second parameter causes the menu to be
installed in the submenu portion of the menu list.) The call to GetMenuHandle gets the
handle to the Special menu, which is used in the following call to SetMenuHierarchicalID
to attach the submenu to the second item in the Special menu.
The following rather large block programmatically assigns command IDs to all items in the
Style (Programmatic), Size, and Special menus and the submenu. (Command IDs for the File
and Style ('xmnu') menus are assigned in the associated 'xmnu' resources. It is not
possible to assign command IDs to this application's items in the system-managed menus
(Apple and Help), nor is it possible to assign command IDs to the items in the Font
menu.)
The following small block programmatically assigns a colour icon to the second item in
the submenu. The call to GetCIcon creates a CIcon data structure and initializes it from
data read in from the specified 'cicn' resource. The handle to this structure is then
passed as the last parameter in the SetMenuItemIconHandle, the third parameter specifying
that the type of icon is a colour icon. (The colour icon for the first second item in
the submenu is assigned in the associated 'xmnu' resource.)
The next block programmatically assigns command-key equivalents to the items of the Size
menu. (Because the keys assigned are the two delete keys and the page-up and page-down
keys, it is not possible to make these assignments within the 'MENU' resource.) Also, a
substitute glyph must be assigned in the case of the two delete keys, otherwise the
correct glyphs will not be displayed. The calls to SetItemCmd assign the specified key
to the menu item. In the case of the first two calls, a substitute glyph is assigned via
calls to SetMenuItemGlyph. If this is not done, the glyphs displayed will not be visual
representations of the delete keys. (These substitute glyphs could also have been
specified in the keyboard glyph fields for these items in the menu's 'xmnu' resource.)
The next block is applicable only to the PowerPC target, and only executes if Mac OS 8.5
or later is present. SetMenuExcludesMarkColumn is called to delete the marking character
column from the Special menu and SetMenuFont is called to set the font for the menu items
in this menu to Gadget (assuming that font is present).
The block beginning with the call to HMGetHelpMenuHandle appends a menu item with the
name "Menus Help" to the Help menu.
The final block sets checkmarks against the appropriate font, style and size menu items
according to the initialised values of the associated global variables.
doMenuChoice
doMenuChoice takes the long integer returned by the MenuSelect and MenuEvent calls,
extracts the menu ID, the menu item number, and the command ID (if any) and switches
according to the menu ID (if no Command ID is present) or the command ID (if present).
Prior to the switch, the menu ID and the menu item number are extracted from the long
integer. An immediate return is made if the high word equals 0, (meaning that either the
mouse button was released when the pointer was outside the menu box or MenuEvent found no
menu list match for the key pressed in conjunction with the Command key).
If the menu ID represents the Apple, Font, or Help menus, the relevant
application-defined functions are called to further handle the menu item choice.
Otherwise, GetMenuItemCommandID is called. GetMenuItemCommandID returns zero as the
function result if the call is successful, and a pointer to an integer representing the
value of the item's command ID will be returned in the third parameter. If the call is
successful, and if a zero is not returned in the third parameter, a command ID exists for
the item. Accordingly, the program switches according to the command ID.
Note that the initial handling of all of the remaining menu items, regardless of which
menu they belong to, is attended to within the one switch in the one function. The
responses to the user choosing the various menu items is the same as in Menus1, except
that the code for checkmarking the Style menu items and changing the current style, and
for checkmarking the Size menu items and storing the current size, has been divided
between this function and two further-handling functions (doCheckStyleMenuItem and
doCheckSizeMenuItem).
Also note that the handling of the two submenu items has been changed to make the items
mutually exclusive.
MenuSelect and MenuEvent leave the menu title highlighted if an item was actually
selected. Accordingly, the last line unhighlights the menu title when the action
associated with the user's drop-down menu choice is complete.
|