tedj@hpcilzb.HP.COM (Ted Johnson) (10/21/88)
[Hier Menu Demo Source] This program demonstrates how to use hierarchical menus. It also demonstrates how to handle DA's, how to make your own "About..." box (with an icon), and how to use dialog boxes. It was written in LSC, and includes the source code, resource file, and stripped project file. The use of this source code is FREE, provided it is for non-profit purposes. I hope it can save someone some time! However the name "T Bear Software" and the T Bear icon are both Copyright (C) 1988 by Ted C. Johnson, and may NOT be used without my express written permission. -Ted Johnson President, T Bear Software [Moderator's Note: The binary for this program has been posted to comp.binaries.mac.] --- #! /bin/sh # This is a shell archive, meaning: # 1. Remove everything above the #! /bin/sh line. # 2. Save the resulting text in a file. # 3. Execute the file with /bin/sh (not csh) to create the files: # # Hier_Menu_Demo.c # Hier_Menu_Demo.r # # This archive created: Thu Oct 20 11:39:07 1988 # By: Roger L. Long (bytebug@dhw68k.cts.com) # export PATH; PATH=/bin:$PATH echo shar: extracting "'Hier_Menu_Demo.c'" '(14524 characters)' if test -f 'Hier_Menu_Demo.c' then echo shar: will not over-write existing file "'Hier_Menu_Demo.c'" else sed 's/^X//' << \SHAR_EOF > 'Hier_Menu_Demo.c' X/* X*Program name: Hier Menu Demo X* X*Author: Ted C. Johnson, Sun, Aug 14 1988. X* X*Compilation instructions: use Lightspeed C, v.2.15. This program DOES X* use a resource file. I developed this program X* on a Mac SE HD20 running System/Finder 4.1/5.5. X* X*Summary: This program demonstrates how to use hierarchical menus. It X* also demonstrates how to handle DA's, how to make your own X* "AboutI" box (with an icon), and how to use dialog boxes. X* X* The use of this source code is free, provided it is for X* non-profit purposes. I hope it can save someone some time! X* X* However the name "T Bear Software" and the T Bear icon are X* both CopyRight ) 1988 by Ted C. Johnson, and may NOT be used X* without my express written permission. X*/ X X X X#include <QuickDraw.h> X#include <WindowMgr.h> X#include <EventMgr.h> X#include <MenuMgr.h> X#include <DialogMgr.h> X#include <FontMgr.h> X#include <DeskMgr.h> X#include <MacTypes.h> X#include <TextEdit.h> X X X X#define int32 long X#define int16 int X#define int8 char X X#define NIL 0L X X X X/*Define the ID for our DLOG and DITL resource.*/ X X#define DIALOG_MESSAGE 777 X X X/* X*Define our menu IDs. My unusual spacing is meant to give you a X*picture of how the sub-menus relate to their parent menu. X*/ X X#define APPLE_ID 10 X X#define FILE_ID 20 X X#define FONT_N_DA_ID 30 X#define FONT_ID 31 /*Fonts.*/ X#define DA_ID 32 /*DA's.*/ X X#define MACINTOSH_ID 40 /*128K, 512K, 512KE, Plus, SE, II*/ X#define SE_ID 41 /*2 diskette, SE HD20*/ X X#define NICE_CAR_ID 100 /*German, Italian, Japanese*/ X#define GERMAN_ID 110 /*Porsche, Mercedes, BMW*/ X#define PORSCHE_ID 111 /*911, 914, 924, 928, 930, 935, 944, 959*/ X#define MERCEDES_ID 112 /*300, 450*/ X#define BMW_ID 113 /*318, 320, 325, 528, 533, 633, 733*/ X#define ITALIAN_ID 120 /*Lamborghini, Ferrari, Lotus*/ X#define JAPANESE_ID 130 /*Honda Prelude, Acura Legend, Mazda RX-7*/ X X X X/*Define our global variables.*/ X XMenuHandle Apple_MH; XMenuHandle File_MH; XMenuHandle FontAndDA_MH; XMenuHandle Font_MH; XMenuHandle DA_MH; XMenuHandle Macintosh_MH; XMenuHandle SE_MH; XMenuHandle NiceCar_MH; XMenuHandle German_MH; XMenuHandle Porsche_MH; XMenuHandle Mercedes_MH; XMenuHandle BMW_MH; XMenuHandle Italian_MH; XMenuHandle Japanese_MH; X X XEventRecord theEvent; XWindowPtr theWindow, whichWindow; Xint16 windowCode; Xint8 theCharacter; X X X Xmain() X{ X InitGraf(&thePort); X InitFonts(); X InitWindows(); X InitMenus(); X TEInit(); X InitDialogs(0L); X InitCursor(); X FlushEvents(everyEvent, 0); X X InitializeOurMenus(); X X X do { X X EventLoop(); X X } while (TRUE); X} X X X XEventLoop() X{ X /* X *Give the DA some time. X */ X X SystemTask(); X X /* X *The event loop. X * X *GetNextEvent() will return FALSE if the event is an event that the X *Desk Manager wants to handle itself (i.e., Desk Accessory events). X *Refer to I.M. I-258. X */ X X if (GetNextEvent(everyEvent, &theEvent) == TRUE) { X switch(theEvent.what) { X X case keyDown: /*Was a key pressed?*/ X theCharacter = theEvent.message & charCodeMask; X if (theEvent.modifiers & cmdKey) { /*Check for a menu*/ X doMenu(MenuKey(theCharacter)); /*equivalent.*/ X HiliteMenu(0); X } X break; X X case mouseDown: X windowCode = FindWindow(theEvent.where, &whichWindow); X switch(windowCode) { X X case inMenuBar: X X /* X *There was a mouseDown in the menu bar. X */ X X doMenu(MenuSelect(theEvent.where)); X break; X X case inSysWindow: X X /* X *SystemClick() calls the Desk Manager to handle X *mouse_down events which occur in a desk accessory X *window (e.g., like in the Control Panel's window). X */ X X SystemClick(&theEvent, whichWindow); X break; X } X X default: X break; X }/*switch(theEvent.what)*/ X }/*if*/ X} X X X XInitializeOurMenus() X{ X Apple_MH = NewMenu(APPLE_ID, "\p\024");/*Desk Accessory menu.*/ X AppendMenu(Apple_MH, "\p^1 Software presentsI;(-"); X AddResMenu(Apple_MH, 'DRVR'); X InsertMenu(Apple_MH, 0); X X File_MH = NewMenu(FILE_ID, "\pFile"); /*File menu.*/ X AppendMenu(File_MH, "\pQuit/Q"); X InsertMenu(File_MH, 0); X X X /* X *Set up our first hierarchical menu: Fonts and DAs. X * X *Note that we can insert menus even before we define their X *sub-menus!!! Octal 033 is hex 1B, which is the <ESC> X *character. Octal 024 is the Apple symbol. X */ X X FontAndDA_MH = NewMenu(FONT_N_DA_ID, "\pFonts and DAs"); X AppendMenu(FontAndDA_MH, "\pFonts/\033;\024/\033"); X InsertMenu(FontAndDA_MH, 0); X X Font_MH = NewMenu(FONT_ID, "\pFonts (this title is invisible)"); X AddResMenu(Font_MH, 'FONT'); X InsertMenu(Font_MH, -1); X SetItemMark(FontAndDA_MH, 1, FONT_ID);/*Insert the Font menu beside X *the 1st FontAndDA menu item. X */ X X X X DA_MH = NewMenu(DA_ID, "\p\024 (this title is invisible)");/*Desk Accessory menu.*/ X AddResMenu(DA_MH, 'DRVR'); X InsertMenu(DA_MH, -1); X SetItemMark(FontAndDA_MH, 2, DA_ID);/*Insert the DA menu beside the X *the 2nd FontAndDA menu item. X */ X X X X /* X *Set up our second hierarchical menu: Nice cars. X * X *Note that we can insert menus even before we define their X *sub-menus!!! X */ X X NiceCar_MH = NewMenu(NICE_CAR_ID, "\pNice cars"); X AppendMenu(NiceCar_MH, "\pGerman/\033;Italian/\033;Japanese/\033"); X InsertMenu(NiceCar_MH, 0); X X X /*Set up and insert the German sub-menu.*/ X X German_MH = NewMenu(GERMAN_ID, "\pthis title is invisible"); X AppendMenu(German_MH, "\pPorsche/\033;Mercedes/\033;BMW/\033"); X InsertMenu(German_MH, -1); X SetItemMark(NiceCar_MH, 1, GERMAN_ID);/*Insert the German menu X *beside the 1st NiceCars X *menu item. X */ X X X /*Set up and insert the Porsche sub-sub-menu.*/ X X Porsche_MH = NewMenu(PORSCHE_ID, "\pthis title is invisible"); X AppendMenu(Porsche_MH, "\p911;914;924;928;930;935;944;959"); X InsertMenu(Porsche_MH, -1); X SetItemMark(German_MH, 1, PORSCHE_ID);/*Insert the Porsche menu X *beside the 1st German X *menu item. X */ X X X /*Set up and insert the Mercedes sub-sub-menu.*/ X X Mercedes_MH = NewMenu(MERCEDES_ID, "\pthis title is invisible"); X AppendMenu(Mercedes_MH, "\p300;450"); X InsertMenu(Mercedes_MH, -1); X SetItemMark(German_MH, 2, MERCEDES_ID);/*Insert the Mercedes X *menu beside the 2nd X *German menu item. X */ X X X /*Set up and insert the BMW sub-sub-menu.*/ X X BMW_MH = NewMenu(BMW_ID, "\pthis title is invisible"); X AppendMenu(BMW_MH, "\p318;320;325;528;633;733"); X InsertMenu(BMW_MH, -1); X SetItemMark(German_MH, 3, BMW_ID); /*Insert the BMW menu X *beside the 3rd German X *menu item. X */ X X X /*Set up and insert the Italian sub-menu.*/ X X Italian_MH = NewMenu(ITALIAN_ID, "\pthis title is invisible"); X AppendMenu(Italian_MH, "\pLamborghini;Ferrari;Lotus"); X InsertMenu(Italian_MH, -1); X SetItemMark(NiceCar_MH, 2, ITALIAN_ID);/*Insert the Italian menu X *beside the 2nd NiceCar X *menu item. X */ X X X /*Set up and insert the Japanese sub-menu.*/ X X Japanese_MH = NewMenu(JAPANESE_ID, "\pthis title is invisible"); X AppendMenu(Japanese_MH, "\pHonda Prelude;Acura Legend;Mazda RX-7"); X InsertMenu(Japanese_MH, -1); X SetItemMark(NiceCar_MH, 3, JAPANESE_ID);/*Insert the Japanese menu X *beside the 3rd NiceCar X *menu item. X */ X X X X /* X *Set up our third hierarchical menu: Macintoshes. X * X *Note that we can insert menus even before we define their X *sub-menus!!! X */ X X Macintosh_MH = NewMenu(MACINTOSH_ID, "\pMacintoshes"); X AppendMenu(Macintosh_MH, "\p128K;512K;512KE;Plus;SE/\033;II"); X InsertMenu(Macintosh_MH, 0); X X /*Set up and insert the SE sub-menu.*/ X SE_MH = NewMenu(SE_ID, "\pthis title is invisible"); X AppendMenu(SE_MH, "\pHD 20;2 diskette"); X InsertMenu(SE_MH, -1); X SetItemMark(Macintosh_MH, 5, SE_ID);/*Insert the SE menu beside the X *5th Macintosh menu item. X */ X X X DrawMenuBar(); X} X X X X/* X*This is the subroutine which handles all of the menu commands. X*/ X XdoMenu(menuResult) Xint32 menuResult; X{ XGrafPtr theCurrentPort; XStr255 theDAsName, menuItemText; Xint16 menuID, itemNumber; X X menuID = HiWord(menuResult); X itemNumber = LoWord(menuResult); X X switch(menuID) { X X case APPLE_ID: X if (itemNumber == 1) { X ShowAboutWindow(); X } X else { X X /* X *Save the current grafPort, in case the DA doesn't X *restore it to the previous value. X */ X X GetPort(&theCurrentPort); X X GetItem(Apple_MH, itemNumber, &theDAsName); X OpenDeskAcc(&theDAsName); X X SetPort(theCurrentPort); X } X break; X X case FILE_ID: /*The "File" menu.*/ X switch(itemNumber) { X case 1: X ExitToShell(); X break; X X default: X break; X }/*switch(itemNumber)*/ X X break; X X /*Handle the sub-menus for the "Font and DAs" hierarchical menu.*/ X case FONT_ID: X switch(itemNumber) { X default: X GetItem(Font_MH, itemNumber, menuItemText); X message("\pYou selected the ", menuItemText, X "\p font."); X break; X } X break; X X case DA_ID: X switch(itemNumber) { X default: X GetItem(DA_MH, itemNumber, menuItemText); X message("\pYou selected the \"", menuItemText, X "\p\" DA."); X X break; X } X break; X X /*Handle the sub-menus for the "Nice cars" hierarchical menu.*/ X case PORSCHE_ID: X switch(itemNumber) { X default: X GetItem(Porsche_MH, itemNumber, menuItemText); X message("\pYou selected the ", X menuItemText, X "\p Porsche."); X break; X } X break; X X case MERCEDES_ID: X switch(itemNumber) { X default: X GetItem(Mercedes_MH, itemNumber, menuItemText); X message("\pYou selected the ", X menuItemText, X "\p Mercedes."); X break; X } X break; X X case BMW_ID: X switch(itemNumber) { X default: X GetItem(BMW_MH, itemNumber, menuItemText); X message("\pYou selected the ", X menuItemText, X "\p BMW."); X break; X } X break; X X case ITALIAN_ID: X switch(itemNumber) { X default: X GetItem(Italian_MH, itemNumber, menuItemText); X message("\pYou selected the ", X menuItemText, "\p."); X break; X } X break; X X case JAPANESE_ID: X switch(itemNumber) { X default: X GetItem(Japanese_MH, itemNumber, menuItemText); X message("\pYou selected the ", X menuItemText, "\p."); X break; X } X break; X X /*Handle the Macintosh menu, and sub-menu.*/ X case MACINTOSH_ID: X switch(itemNumber) { X default: X GetItem(Macintosh_MH, itemNumber, menuItemText); X message("\pYou selected the Mac ", X menuItemText, "\p."); X break; X } X break; X X case SE_ID: X switch(itemNumber) { X default: X GetItem(SE_MH, itemNumber, menuItemText); X message("\pYou selected the Mac SE ", X menuItemText, "\p."); X break; X } X break; X X default: X break; X }/*switch(menuID)*/ X X HiliteMenu(0);/*Don't forget to un-hilite the menu bar after X you're done performing that menu item command.*/ X} X X X X/* X*ShowAboutWindow() puts up a window when the user selects the "About DAI" X*command from the apple menu. To exit this window and return to the X*program, the user has to click the mouse button. X*/ X XShowAboutWindow() X{ XEventRecord theEvent; XGrafPtr DA_AboutBox_Port; XWindowPtr AboutWindow; XRect AboutRect, RectForOneLineOfText; Xint8 *line1, *line2, *line3, *line4, *line5; X X line1 = "Hier Menu Demo,"; X line2 = "a tutorial program"; X line3 = "by Ted C. Johnson"; X line4 = "President of T Bear Software*"; X line5 = "Copyright ) 1988 by Ted C. Johnson"; X X GetPort(&DA_AboutBox_Port); /*Preserve the DA_About_Box port.*/ X X SetRect(&AboutRect, 75, 110, 425, 230);/*Window size and position.*/ X X SetRect(&RectForOneLineOfText, 5, 10, 345, 25);/*Box for first line of text.*/ X X AboutWindow = NewWindow((WindowPeek)NIL, &AboutRect, "\p", TRUE, X altDBoxProc, (WindowPtr)-1, TRUE, 0); X SetPort(AboutWindow); X X /* X *Choose the system font (Chicago), 12 point size. X */ X X TextSize(12); X X X TextFont(systemFont); X X /* X *Draw the text. Offset the RectForOneLineOfText box 20 pixels down and X *and 0 pixels the right, for each line of text. Use different styles X *of text for each line, just for the heck of it. See I.M, page I-171. X */ X X TextFace(shadow); X TextBox(line1, strlen(line1), &RectForOneLineOfText, teJustCenter); X X OffsetRect(&RectForOneLineOfText, 0, 20); X TextFace(underline); X TextBox(line2, strlen(line2), &RectForOneLineOfText, teJustCenter); X X OffsetRect(&RectForOneLineOfText, 0, 20); X TextFace(italic); X TextBox(line3, strlen(line3), &RectForOneLineOfText, teJustCenter); X X OffsetRect(&RectForOneLineOfText, 0, 20); X TextFace(bold); X TextBox(line4, strlen(line4), &RectForOneLineOfText, teJustCenter); X X OffsetRect(&RectForOneLineOfText, 0, 20); X TextFace(0); X TextBox(line5, strlen(line5), &RectForOneLineOfText, teJustCenter); X X /* X *Wait for a mouse-down event. When you get one, erase the About X *Window, and return to DA_AboutBox Demo window. X */ X X do { X X GetNextEvent(everyEvent, &theEvent); X X } while (theEvent.what != mouseDown); X X /* X *DisposeWindow() calls CloseWindow(), then releases the memory X *occupied by the window record. X */ X X DisposeWindow(AboutWindow); X X SetPort(DA_AboutBox_Port); X} X X X X/* X*showDialog() puts up a modal dialog box and returns the X*number corresponding to the button pushed. X*/ X Xint16 showDialog(dialogNumber, maxbutton) Xint16 dialogNumber; Xint16 maxbutton; X{ XDialogPtr dialog; /* pointer to the dialog */ XDialogRecord dialogRecord; /* actual dialog record */ Xint16 itemHit = maxbutton + 1; X X /* bring up the dialog box */ X dialog = GetNewDialog(dialogNumber, &dialogRecord, (WindowPtr) -1); X ShowWindow(dialog); X X while (itemHit > maxbutton) X { X ModalDialog((ProcPtr) NIL, &itemHit); X } X X CloseDialog(dialog); X X return(itemHit); X} X X X Xmessage(string1, string2, string3) Xint8 *string1, *string2, *string3; /* expect pascal string */ X{ X ParamText(string1, string2, string3, "\p"); X showDialog(DIALOG_MESSAGE, 1); X} X X X XmessageWithInt(string, theInt) Xint8 *string; /* expect pascal string */ Xint16 theInt; X{ XStr255 tempString; X X NumToString(theInt, &tempString); X ParamText(string, tempString, "\p", "\p"); X showDialog(DIALOG_MESSAGE, 1); X} X X Xstrlen(s) Xregister int8 *s; X{ Xint8 *s0 = s; X X while(*s++); X return(s - s0 -1); X} SHAR_EOF echo shar: 6 control characters may be missing from "'Hier_Menu_Demo.c'" if test 14524 -ne "`wc -c < 'Hier_Menu_Demo.c'`" then echo shar: error transmitting "'Hier_Menu_Demo.c'" '(should have been 14524 characters)' fi fi # end of overwriting check echo shar: extracting "'Hier_Menu_Demo.r'" '(852 characters)' if test -f 'Hier_Menu_Demo.r' then echo shar: will not over-write existing file "'Hier_Menu_Demo.r'" else sed 's/^X//' << \SHAR_EOF > 'Hier_Menu_Demo.r' Xresource 'ICON' (257) X{ X 0x1cff 0x3800 0x2300 0xc41f X 0x2000 0x0404 0x2800 0x1404 X 0x2800 0x1404 0x3000 0x0c04 X 0x0866 0x1000 0x0866 0x1000 X 0x1000 0x081e 0x1000 0x0811 X 0x103c 0x081e 0x1018 0x0811 X 0x0891 0x101e 0x387e 0x1c00 X 0x4400 0x221f 0x83ff 0xc210 X 0x8001 0xc21c 0x9f82 0x2210 X 0x9044 0x221f 0x903f 0xc200 X 0x9000 0x0404 0x4f80 0x080a X 0x2070 0x340e 0x5f8f 0xc411 X 0x4000 0x0411 0x4000 0x0400 X 0x4000 0x041e 0x4000 0x0411 X 0x3e00 0xf81f 0x4101 0x0414 X 0x55ff 0x5412 0x7f01 0xfc11 X}; X Xresource 'DLOG' (777 , "message") X{ X {46, 92, 190, 394}, X 1, X visible, X goAway, X 0x0, X 777, X "this is my dialog" X}; X Xresource 'DITL' (777) X{ X { X {101, 120, 134, 187}, X Button {enabled, "OK"}; X {15, 24, 86, 295}, X StaticText {disabled, "^0^1^2^3"} X } X}; X SHAR_EOF if test 852 -ne "`wc -c < 'Hier_Menu_Demo.r'`" then echo shar: error transmitting "'Hier_Menu_Demo.r'" '(should have been 852 characters)' fi fi # end of overwriting check # End of shell archive exit 0 ---