Home > Articles > Home & Office Computing > Mac OS X

  • Print
  • + Share This
This chapter is from the book

This chapter is from the book

Demonstration Program Menus1 Listing

// *******************************************************************************************
// Menus1.c                CLASSIC EVENT MODEL
// *******************************************************************************************
//
// This program:
//
//  Opens a window.
//
//  Creates these pull-down menus: Apple, File, Edit, Font, Size, Special, and Window.
//
//  Displays text in the window indicating the menu selection made by the user.
//
// The Apple menu includes an "About..." menu item for the program.
//
// The second menu item in the Special menu contains a submenu.
//
// The Font and Window menus are created programmatically using the functions
// CreateStandardFontMenu and CreateStandardWindowMenu.
//
// 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.
//
// 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/close
// button.
//
// The program utilises the following resources:
//
//  A 'plst' resource.
//
//  A 'WIND' resource (purgeable) (initially not visible).
//
//  An 'MBAR' resource (preload, non-purgeable).
//
//  'MENU' resources for the Apple, File, Edit, Font, Size, and Special drop-down menus
// and the submenu (all preload, all non-purgeable).
//
//  A 'SIZE' resource with the acceptSuspendResumeEvents, canBackground,
// doesActivateOnFGSwitch, and isHighLevelEventAware flags set.
//
// *******************************************************************************************

// ...................................................................................includes

#include <Carbon.h>

// ...................................................................................defines

#define rMenubar   128
#define mAppleApplication 128
#define iAbout   1
#define mFile    129
#define iQuit   12
#define mEdit    130
#define iUndo   1
#define iCut    3
#define iCopy   4
#define iPaste   5
#define iClear   6
#define mFont    131
#define mSize    132
#define iTen    1
#define iTwelve   2
#define iEighteen  3
#define iTwentyFour  4
#define mSpecial   133
#define iFirstItem  1
#define iSecondItem  2
#define mWindow   134
#define mSubmenu   135
#define mFirstFontSubMenu 136
#define iFirstSubItem 1
#define iSecondSubItem 2
#define rWindowResource 128

// ..............................................................................global variables

Boolean  gDone;
ItemCount  gFontMenuHierMenuCount;
MenuItemIndex gCurrentFontSizeItem = 2;
MenuItemIndex gCurrentFontMenuItem;
MenuItemIndex gCurrentFontSubMenuItem;
MenuRef  gCurrentFontSubMenuRef = NULL;

// ..............................................................................function prototypes

void main     (void);
void doPreliminaries  (void);
OSErr quitAppEventHandler (AppleEvent *,AppleEvent *,SInt32);
void doGetMenus    (void);
void doEvents    (EventRecord *);
void doMouseDown   (EventRecord *);
void doAdjustMenus   (void);
void doMenuChoice   (SInt32);
void doAppleApplicationMenu (MenuItemIndex);
void doFileMenu    (MenuItemIndex);
void doEditMenu    (MenuItemIndex);
void doFontMenu    (MenuID,MenuItemIndex);
void doSizeMenu    (MenuItemIndex);
void doSpecialMenu   (MenuItemIndex);
void doSubMenus    (MenuItemIndex);
void drawItemString   (Str255);

// ************************************************************************************** main

void main(void)
{
 EventRecord eventStructure;
 WindowRef windowRef;

 // ...............................................................................do preliminaries

 doPreliminaries();

 // ...............................................................................open a window

 if(!(windowRef = GetNewCWindow(rWindowResource,NULL,(WindowRef) -1)))
 {
 SysBeep(10);
 ExitToShell();
 }

 SetPortWindowPort(windowRef);

 // ....................................................set up menu bar and menus, then show window

 doGetMenus();
 ShowWindow(windowRef);

 // ..................................................................................event loop

 gDone = false;

 while(!gDone)
 {
 if(WaitNextEvent(everyEvent,&eventStructure,180,NULL))
  doEvents(&eventStructure);
 }
}

// *************************************************************************** doPreliminaries

void doPreliminaries(void)
{
 OSErr osError;

 MoreMasterPointers(640);
 InitCursor();
 FlushEvents(everyEvent,0);

 osError = AEInstallEventHandler(kCoreEventClass,kAEQuitApplication,
       NewAEEventHandlerUPP((AEEventHandlerProcPtr) quitAppEventHandler),
       0L,false);
 if(osError != noErr)
 ExitToShell();
}

// **************************************************************************** doQuitAppEvent

OSErr quitAppEventHandler(AppleEvent *appEvent,AppleEvent *reply,SInt32 handlerRefcon)
{
 OSErr osError;
 DescType returnedType;
 Size  actualSize;

 osError = AEGetAttributePtr(appEvent,keyMissedKeywordAttr,typeWildCard,&returnedType,NULL,0,
        &actualSize);

 if(osError == errAEDescNotFound)
 {
 gDone = true;
 osError = noErr;
 }
 else if(osError == noErr)
 osError = errAEParamMissed;

 return osError;
}

// ******************************************************************************** doGetMenus

void doGetMenus(void)
{
 MenuBarHandle menubarHdl;
 SInt32  response;
 MenuRef  menuRef;
 OSStatus  osError;
 Str255  smallSystemFontName, itemString;
 SInt16  numberOfItems,a;

 // ...................................................................get and set, and menu bar

 menubarHdl = GetNewMBar(rMenubar);
 if(menubarHdl == NULL)
 ExitToShell();
 SetMenuBar(menubarHdl);

 // ..................if running on Mac OS X, delete Quit item and preceding divider from File menu

 Gestalt(gestaltMenuMgrAttr,&response);
 if(response & gestaltMenuMgrAquaLayoutMask)
 {
 menuRef = GetMenuRef(mFile);
 if(menuRef != NULL)
 {
  DeleteMenuItem(menuRef,iQuit);
  DeleteMenuItem(menuRef,iQuit - 1);
  DisableMenuItem(menuRef,0);
 }
 }

 // ................................ create hirearchical Font menu, checkmark small system font

 menuRef = GetMenuRef(mFont);
 if(menuRef != NULL)
 {
 osError = CreateStandardFontMenu(menuRef,0,mFirstFontSubMenu,kHierarchicalFontMenuOption,
          &gFontMenuHierMenuCount);
 if(osError != noErr)
  ExitToShell();
 }
 else
 ExitToShell();

 GetFontName(kThemeSmallSystemFont,smallSystemFontName);
 numberOfItems = CountMenuItems(menuRef);
 for(a=1;a<numberOfItems + 1;a++)
 {
 GetMenuItemText(menuRef,a,itemString);
 if(EqualString(itemString,smallSystemFontName,false,false))
 {
  CheckMenuItem(menuRef,a,true);
  gCurrentFontMenuItem = a;
  break;
 }
 }

 // .................................................create Window menu and insert into menu list

 CreateStandardWindowMenu(0,&menuRef);
 SetMenuID(menuRef,mWindow);
 InsertMenu(menuRef,0);

 // ......................................................get submenus and insert into window list

 menuRef = GetMenu(mSubmenu);
 if(menuRef != NULL)
 InsertMenu(menuRef,hierMenu);
 else
 ExitToShell();

 // ............................. set initial font size and checkmark associated item in Size menu

 doSizeMenu(gCurrentFontSizeItem);

 // ...............................................................................draw menu bar

 DrawMenuBar();
 }

// ********************************************************************************** doEvents

void doEvents(EventRecord *eventStrucPtr)
{
 switch(eventStrucPtr->what)
 {
 case kHighLevelEvent:
  AEProcessAppleEvent(eventStrucPtr);
  break;

 case mouseDown:
  doMouseDown(eventStrucPtr);
  break;

 case keyDown:
  if((eventStrucPtr->modifiers & cmdKey) != 0)
  {
  doAdjustMenus();
  doMenuChoice(MenuEvent(eventStrucPtr));
  }
  break;

 case updateEvt:
  BeginUpdate((WindowRef) eventStrucPtr->message);
  EndUpdate((WindowRef) eventStrucPtr->message);
  break;
 }
}

// ******************************************************************************* doMouseDown

void doMouseDown(EventRecord *eventStrucPtr)
{
 WindowRef  windowRef;
 WindowPartCode partCode;
 SInt32   menuChoice;

 partCode = FindWindow(eventStrucPtr->where,&windowRef);

 switch(partCode)
 {
 case inMenuBar:
  doAdjustMenus();
  menuChoice = MenuSelect(eventStrucPtr->where);
  doMenuChoice(menuChoice);
  break;

 case inContent:
  if(windowRef != FrontWindow())
  SelectWindow(windowRef);
  break;

 case inDrag:
  DragWindow(windowRef,eventStrucPtr->where,NULL);
  break;

 case inGoAway:
  if(TrackGoAway(windowRef,eventStrucPtr->where))
  gDone = true;
  break;
 }
}

// ***************************************************************************** doAdjustMenus

void doAdjustMenus(void)
{
 // Adjust menus here.
}

// ****************************************************************************** doMenuChoice

void doMenuChoice(SInt32 menuChoice)
{
 MenuID  menuID;
 MenuItemIndex menuItem;

 menuID = HiWord(menuChoice);
 menuItem = LoWord(menuChoice);

 if(menuID == 0)
 return;

 if(menuID == mFont || ((menuID >= mFirstFontSubMenu) &&
       (menuID <= mFirstFontSubMenu + gFontMenuHierMenuCount)))
 doFontMenu(menuID,menuItem);
 else
 {
 switch(menuID)
 {
  case mAppleApplication:
  doAppleApplicationMenu(menuItem);
  break;

  case mFile:
  doFileMenu(menuItem);
  break;

  case mEdit:
  doEditMenu(menuItem);
  break;

  case mSize:
  doSizeMenu(menuItem);
  break;

  case mSpecial:
  doSpecialMenu(menuItem);
  break;

  case mSubmenu:
  doSubMenus(menuItem);
  break;
 }
 }

 HiliteMenu(0);
}

// ******************************************************************** doAppleApplicationMenu

void doAppleApplicationMenu(MenuItemIndex menuItem)
{
 if(menuItem == iAbout)
 drawItemString("\pAbout Menus1");
}

// ******************************************************************************** doFileMenu

void doFileMenu(MenuItemIndex menuItem)
{
 if(menuItem == iQuit)
 gDone = true;
}

// ******************************************************************************** doEditMenu

void doEditMenu(MenuItemIndex 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(MenuID menuID,MenuItemIndex menuItem)
{
 MenuRef  menuRef, fontMenuRef;
 OSStatus  osError;
 FMFontFamily currentFontFamilyReference;
 FMFontStyle currentFontStyle;
 Str255  fontName, styleName, itemName;
 SInt16  a, numberOfFontMenuItems;

 menuRef = GetMenuRef(menuID);

 osError = GetFontFamilyFromMenuSelection(menuRef,menuItem,&currentFontFamilyReference,
           &currentFontStyle);
 if(osError == noErr)
 {
 TextFont(currentFontFamilyReference);
 TextFace(currentFontStyle);

 GetFontName(currentFontFamilyReference,fontName);
 drawItemString(fontName);

 if(menuID == mFont)
 {
  CheckMenuItem(menuRef,gCurrentFontMenuItem,false);
  gCurrentFontMenuItem = menuItem;
  CheckMenuItem(menuRef,gCurrentFontMenuItem,true);

  if(gCurrentFontSubMenuRef != NULL)
  CheckMenuItem(gCurrentFontSubMenuRef,gCurrentFontSubMenuItem,false);
 }
 else
 {
  if(gCurrentFontSubMenuRef != NULL)
  CheckMenuItem(gCurrentFontSubMenuRef,gCurrentFontSubMenuItem,false);
  gCurrentFontSubMenuRef = menuRef;
  gCurrentFontSubMenuItem = menuItem;
  CheckMenuItem(gCurrentFontSubMenuRef,gCurrentFontSubMenuItem,true);

  fontMenuRef = GetMenuRef(mFont);
  CheckMenuItem(fontMenuRef,gCurrentFontMenuItem,false);

  numberOfFontMenuItems = CountMenuItems(fontMenuRef);

  for(a=1;a<=numberOfFontMenuItems;a++)
  {
  GetMenuItemText(fontMenuRef,a,itemName);
  if(EqualString(fontName,itemName,true,true))
  {
   gCurrentFontMenuItem = a;
   break;
  }
  }

  SetItemMark(fontMenuRef,gCurrentFontMenuItem,'-');

  GetMenuItemText(menuRef,menuItem,styleName);
  DrawString("\p ");
  DrawString(styleName);
 }
 }
 else
 ExitToShell();
}

// ******************************************************************************** doSizeMenu

void doSizeMenu(MenuItemIndex menuItem)
{
 MenuRef sizeMenuRef;

 switch(menuItem)
 {
 case iTen:
  TextSize(10);
  break;

 case iTwelve:
  TextSize(12);
  break;

 case iEighteen:
  TextSize(18);
  break;

 case iTwentyFour:
  TextSize(24);
  break;
 }

 sizeMenuRef = GetMenuRef(mSize);

 CheckMenuItem(sizeMenuRef,gCurrentFontSizeItem,false);
 CheckMenuItem(sizeMenuRef,menuItem,true);

 gCurrentFontSizeItem = menuItem;

 drawItemString("\pSize change");
}

// ***************************************************************************** doSpecialMenu

void doSpecialMenu(MenuItemIndex menuItem)
{
 if(menuItem == iFirstItem)
 drawItemString("\pFirst Item");
}

// ******************************************************************************** doSubMenus

void doSubMenus(MenuItemIndex menuItem)
{
 switch(menuItem)
 {
 case iFirstSubItem:
  drawItemString("\pSubitem 1");
  break;

 case iSecondSubItem:
  drawItemString("\pSubitem 2");
  break;
 }
}

// **************************************************************************** drawItemString

void drawItemString(Str255 eventString)
{
 RgnHandle tempRegion;
 WindowRef windowRef;
 Rect  scrollBox;

 windowRef = FrontWindow();
 tempRegion = NewRgn();

 GetWindowPortBounds(windowRef,&scrollBox);

 ScrollRect(&scrollBox,0,-24,tempRegion);
 DisposeRgn(tempRegion);

 MoveTo(8,286);
 DrawString(eventString);
}

// *******************************************************************************************
  • + Share This
  • 🔖 Save To Your Account