home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
ftp.mactech.com 2010
/
ftp.mactech.com.tar
/
ftp.mactech.com
/
macintosh-c
/
macc-carbon-demos-nonbinhex.sit
/
macc-carbon-demos-nonbinhex
/
chap10-demo
/
AppleEvents.c
< prev
next >
Wrap
C/C++ Source or Header
|
2001-05-07
|
24KB
|
821 lines
// *******************************************************************************************
// AppleEvents.c CLASSIC EVENT MODEL
// *******************************************************************************************
//
// This program:
//
// • Installs handlers for the required Apple events, Appearance Manager Apple events, and,
// on Mac OS X only, the Show Preferences Apple event.
//
// • Responds to the receipt of required Apple events by displaying descriptive text in a
// window opened for that purpose, and by opening simulated document windows as
// appropriate. These responses result from the user:
//
// • Double clicking on the application's icon, or selecting the icon and choosing Open
// from the Finder's File menu, thus causing the receipt of an Open Application event.
//
// • When the application is already open, double clicking on the application's icon, or
// selecting the icon and choosing Open from the Finder's File menu, thus causing the
// receipt of a Re-open Application event.
//
// • Double clicking on one of the document icons, selecting one or both of the document
// icons and choosing Open from the Finder's File menu, or dragging one or both of the
// document icons onto the application's icon, thus causing the receipt of an Open
// Documents event.
//
// • On Mac OS 8/9, selecting one or both of the document icons and choosing Print from
// the Finder's file menu, thus causing the receipt of a Print Documents event and, if
// the application is not already running, a subsequent Quit Application event.
//
// • While the application is running, choosing Shut Down or Restart from the Finder's
// Special menu, thus causing the receipt of a Quit Application event.
//
// • Responds to the receipt of Appearance Manager Apple events (Mac OS 8/9) and the Show
// Preferences Apple event (Mac OS X) by displaying descriptive text.
//
// The program, which is intended to be run as a built application rather than within
// CodeWarrior, utilises the following resources:
//
// • A 'plst' resource containing an information property list which provides information
// to the Mac OS X Finder.
//
// • An 'icns' resource containing application and document icons for Mac OS X.
//
// • 'WIND' resources (purgeable, initially visible) for the descriptive text display window
// and simulated document windows.
//
// • 'MBAR' and 'MENU' resources (preload, non-purgeable).
//
// • 'STR#' resources (purgeable) for displaying error messages using StandardAlert.
//
// • For Mac OS 8/9:
//
// • 'ICN#', 'ics#', 'ics4', 'ics8', 'icl4', and 'icl8' resources (that is, an icon
// family) for the application and for the application's documents. (Purgeable.)
//
// • 'FREF' resources (non-purgeable) for the application and the application's 'TEXT'
// documents, which link the icons with the file types they represent, and which allow
// users to launch the application by dragging the document icons to the application
// icon.
//
// • The application's signature resource (non-purgeable), which enables the Finder to
// identify and start up the application when the user double clicks the application's
// document icons.
//
// • A 'BNDL' resource (non-purgeable), which groups together the application's
// signature, icon and 'FREF' resources.
//
// • A 'hfdr' resource (purgeable), which provides the customised finder icon help
// override help balloon for the application icon.
//
// • A 'vers' resource (purgeable), which provides version information via the Show Info
// window and the Version column in list view windows.
//
// • A 'SIZE' resource with the acceptSuspendResumeEvents, canBackground,
// doesActivateOnFGSwitch, and isHighLevelEventAware flags set.
//
// *******************************************************************************************
// ………………………………………………………………………………………………………………………………………………………………………………………………………………………… includes
#include <Carbon.h>
// …………………………………………………………………………………………………………………………………………………………………………………………………………………………… defines
#define rMenubar 128
#define mFile 129
#define iQuit 12
#define rDisplayWindow 128
#define rDocWindow 129
#define rErrorStrings 128
#define eInstallHandler 1
#define eGetRequiredParam 2
#define eGetDescriptorRecord 3
#define eMissedRequiredParam 4
#define eCountDescripRecords 5
#define eCannotOpenFile 6
#define eCannotPrintFile 7
#define eCannotOpenWindow 8
#define eMenus 9
#define MIN(a,b) ((a) < (b) ? (a) : (b))
// …………………………………………………………………………………………………………………………………………………………………………………………………… global variables
WindowRef gWindowRef;
Boolean gRunningOnX = false;
Boolean gDone;
Boolean gApplicationWasOpen = false;
// …………………………………………………………………………………………………………………………………………………………………………………………… function prototypes
void main (void);
void doPreliminaries (void);
void doInstallAEHandlers (void);
void doInstallAnAEHandler (AEEventClass,AEEventID,void *);
void doEvents (EventRecord *);
OSErr openAppEventHandler (AppleEvent *,AppleEvent *,SInt32);
OSErr reopenAppEventHandler (AppleEvent *,AppleEvent *,SInt32);
OSErr openDocsEventHandler (AppleEvent *,AppleEvent *,SInt32);
OSErr printDocsEventHandler (AppleEvent *,AppleEvent *,SInt32);
OSErr quitAppEventHandler (AppleEvent *,AppleEvent *,SInt32);
OSErr sysFontChangeEventHandler (AppleEvent *,AppleEvent *,SInt32);
OSErr smallSysFontChangeEventHandler (AppleEvent *,AppleEvent *,SInt32);
OSErr viewsFontChangeEventHandler (AppleEvent *,AppleEvent *,SInt32);
OSErr showPreferencesEventHandler (AppleEvent *,AppleEvent *,SInt32);
OSErr doHasGotRequiredParams (AppleEvent *);
Boolean doOpenFile (FSSpec *,SInt32,SInt32);
Boolean doPrintFile (FSSpec *,SInt32,SInt32);
void doPrepareToTerminate (void);
WindowRef doNewWindow (void);
void doMenuChoice (SInt32);
void doErrorAlert (SInt16);
void doDrawText (Str255);
void doConcatPStrings (Str255,Str255);
// ************************************************************************************** main
void main(void)
{
Rect portRect;
RGBColor foreColour = { 0xFFFF,0xFFFF,0xFFFF };
RGBColor backColour = { 0x4444,0x4444,0x9999 };
MenuBarHandle menubarHdl;
SInt32 response;
MenuRef menuRef;
EventRecord eventStructure;
// ……………………………………………………………………………………………………………………………………………………………………………………………… do preliminaries
doPreliminaries();
// ……………………………………………………………………………………………………………………………………………………………………… set up menu bar and menus
menubarHdl = GetNewMBar(rMenubar);
if(menubarHdl == NULL)
doErrorAlert(eMenus);
SetMenuBar(menubarHdl);
DrawMenuBar();
Gestalt(gestaltMenuMgrAttr,&response);
if(response & gestaltMenuMgrAquaLayoutMask)
{
menuRef = GetMenuRef(mFile);
if(menuRef != NULL)
{
DeleteMenuItem(menuRef,iQuit);
DeleteMenuItem(menuRef,iQuit - 1);
DisableMenuItem(menuRef,0);
}
gRunningOnX = true;
EnableMenuCommand(NULL,kAEShowPreferences);
}
// ……………………………………………………………………………………………………………………………………………………………………………………………………… open a window
if(!(gWindowRef = GetNewCWindow(rDisplayWindow,NULL,(WindowRef) -1)))
{
doErrorAlert(eCannotOpenWindow);
ExitToShell();
}
SetPortWindowPort(gWindowRef);
TextSize(10);
TextFace(bold);
RGBBackColor(&backColour);
RGBForeColor(&foreColour);
GetWindowPortBounds(gWindowRef,&portRect);
EraseRect(&portRect);
// ……………………………………………………………………………………………………………………………………………………………… install Apple event handlers
doInstallAEHandlers();
// ……………………………………………………………………………………………………………………………………………………………………………………………………………… event loop
gDone = false;
while(!gDone)
{
if(WaitNextEvent(everyEvent,&eventStructure,180,NULL))
doEvents(&eventStructure);
}
}
// *************************************************************************** doPreliminaries
void doPreliminaries(void)
{
MoreMasterPointers(64);
InitCursor();
FlushEvents(everyEvent,0);
}
// *********************************************************************** doInstallAEHandlers
void doInstallAEHandlers(void)
{
// ………………………………………………………………………………………………………………………………………………………………………………… required Apple events
doInstallAnAEHandler(kCoreEventClass,kAEOpenApplication,openAppEventHandler);
doInstallAnAEHandler(kCoreEventClass,kAEReopenApplication,reopenAppEventHandler);
doInstallAnAEHandler(kCoreEventClass,kAEOpenDocuments,openDocsEventHandler);
doInstallAnAEHandler(kCoreEventClass,kAEPrintDocuments,printDocsEventHandler);
doInstallAnAEHandler(kCoreEventClass,kAEQuitApplication,quitAppEventHandler);
// ……………………………………………………………………………………………………………………………………………………… Appearance Manager Apple events
doInstallAnAEHandler(kAppearanceEventClass,kAESystemFontChanged,sysFontChangeEventHandler);
doInstallAnAEHandler(kAppearanceEventClass,kAESmallSystemFontChanged,
smallSysFontChangeEventHandler);
doInstallAnAEHandler(kAppearanceEventClass,kAEViewsFontChanged,viewsFontChangeEventHandler);
// ……………………………………………………………………………………………………………………………………………………………… Show Preferences Apple event
if(gRunningOnX)
doInstallAnAEHandler(kCoreEventClass,kAEShowPreferences,showPreferencesEventHandler);
}
// ********************************************************************** doInstallAnAEHandler
void doInstallAnAEHandler(AEEventClass eventClass,AEEventID eventID,void *theHandler)
{
OSErr osError;
osError = AEInstallEventHandler(eventClass,eventID,
NewAEEventHandlerUPP((AEEventHandlerProcPtr) theHandler),
0L,false);
if(osError != noErr)
doErrorAlert(eInstallHandler);
}
// ********************************************************************************** doEvents
void doEvents(EventRecord *eventStrucPtr)
{
WindowPartCode partCode;
WindowRef windowRef;
SInt32 menuChoice;
switch(eventStrucPtr->what)
{
case kHighLevelEvent:
AEProcessAppleEvent(eventStrucPtr);
break;
case mouseDown:
partCode = FindWindow(eventStrucPtr->where,&windowRef);
switch(partCode)
{
case inMenuBar:
menuChoice = MenuSelect(eventStrucPtr->where);
doMenuChoice(menuChoice);
break;
case inDrag:
DragWindow(windowRef,eventStrucPtr->where,NULL);
break;
case inContent:
if(windowRef != FrontWindow())
SelectWindow(windowRef);
break;
case inGoAway:
DisposeWindow(windowRef);
break;
}
break;
case keyDown:
if((eventStrucPtr->modifiers & cmdKey) != 0)
doMenuChoice(MenuEvent(eventStrucPtr));
break;
case updateEvt:
BeginUpdate((WindowRef)eventStrucPtr->message);
EndUpdate((WindowRef)eventStrucPtr->message);
break;
}
}
// *********************************************************************** openAppEventHandler
OSErr openAppEventHandler(AppleEvent *appEvent,AppleEvent *reply,SInt32 handlerRefCon)
{
OSErr osError;
WindowRef windowRef;
gApplicationWasOpen = true;
osError = doHasGotRequiredParams(appEvent);
if(osError == noErr)
{
doDrawText("\pReceived an Apple event: OPEN APPLICATION.");
doDrawText("\p • Opening an untitled window in response.");
windowRef = doNewWindow();
SetWTitle(windowRef,"\puntitled");
}
return osError;
}
// ********************************************************************* reopenAppEventHandler
OSErr reopenAppEventHandler(AppleEvent *appEvent,AppleEvent *reply,SInt32 handlerRefCon)
{
OSErr osError;
WindowRef windowRef;
osError = doHasGotRequiredParams(appEvent);
if(osError == noErr)
{
doDrawText("\pReceived an Apple event: RE-OPEN APPLICATION.");
doDrawText("\p • I will check whether I have any windows open.");
windowRef = GetWindowList();
if((windowRef = GetNextWindow(windowRef)) == NULL)
{
doDrawText("\p No windows are open, so I will open a window.");
windowRef = doNewWindow();
SetWTitle(windowRef,"\puntitled 1");
}
else
doDrawText("\p A window is open, so I won't open another.");
}
return osError;
}
// ********************************************************************** openDocsEventHandler
OSErr openDocsEventHandler(AppleEvent *appEvent,AppleEvent *reply,SInt32 handlerRefcon)
{
AEDescList docList;
OSErr osError, ignoreErr;
SInt32 numberOfItems, index;
DescType returnedType;
FSSpec fileSpec;
AEKeyword keyWord;
Size actualSize;
Boolean result;
osError = AEGetParamDesc(appEvent,keyDirectObject,typeAEList,&docList);
if(osError == noErr)
{
osError = doHasGotRequiredParams(appEvent);
if(osError == noErr)
{
osError = AECountItems(&docList,&numberOfItems);
if(osError == noErr)
{
for(index=1;index<=numberOfItems;index++)
{
osError = AEGetNthPtr(&docList,index,typeFSS,&keyWord,&returnedType,&fileSpec,
sizeof(fileSpec),&actualSize);
if(osError == noErr)
{
if(!(result = doOpenFile(&fileSpec,index,numberOfItems)))
doErrorAlert(eCannotOpenFile);
}
else
doErrorAlert(eGetDescriptorRecord);
}
}
else
doErrorAlert(eCountDescripRecords);
}
else
doErrorAlert(eMissedRequiredParam);
ignoreErr = AEDisposeDesc(&docList);
}
else
doErrorAlert(eGetRequiredParam);
return osError;
}
// ********************************************************************* printDocsEventHandler
OSErr printDocsEventHandler(AppleEvent *appEvent,AppleEvent *reply,SInt32 handlerRefcon)
{
AEDescList docList;
OSErr osError, ignoreErr;
SInt32 numberOfItems, index;
DescType returnedType;
FSSpec fileSpec;
AEKeyword keyWord;
Size actualSize;
Boolean result;
osError = AEGetParamDesc(appEvent,keyDirectObject,typeAEList,&docList);
if(osError == noErr)
{
osError = doHasGotRequiredParams(appEvent);
if(osError == noErr)
{
osError = AECountItems(&docList,&numberOfItems);
if(osError == noErr)
{
for(index=1;index<=numberOfItems;index++)
{
osError = AEGetNthPtr(&docList,index,typeFSS,&keyWord,&returnedType,&fileSpec,
sizeof(fileSpec),&actualSize);
if(osError == noErr)
{
if(!(result = doPrintFile(&fileSpec,index,numberOfItems)))
doErrorAlert(eCannotPrintFile);
}
else
doErrorAlert(eGetDescriptorRecord);
}
}
else
doErrorAlert(eCountDescripRecords);
}
else
doErrorAlert(eMissedRequiredParam);
ignoreErr = AEDisposeDesc(&docList);
}
else
doErrorAlert(eGetRequiredParam);
return osError;
}
// *********************************************************************** quitAppEventHandler
OSErr quitAppEventHandler(AppleEvent *appEvent,AppleEvent *reply,SInt32 handlerRefcon)
{
OSErr osError;
osError = doHasGotRequiredParams(appEvent);
if(osError == noErr)
doPrepareToTerminate();
return osError;
}
// ***************************************************************** sysFontChangeEventHandler
OSErr sysFontChangeEventHandler(AppleEvent *appEvent,AppleEvent *reply,
SInt32 handlerRefcon)
{
OSErr osError;
Rect portRect;
Str255 fontName, theString = "\p Current large system font is: ";
osError = doHasGotRequiredParams(appEvent);
if(osError == noErr)
{
GetWindowPortBounds(gWindowRef,&portRect);
EraseRect(&portRect);
doDrawText("\pReceived an Apple event: LARGE SYSTEM FONT CHANGED.");
GetThemeFont(kThemeSystemFont,smSystemScript,fontName,NULL,NULL);
doConcatPStrings(theString,fontName);
doDrawText(theString);
// Action as required by application.
}
return osError;
}
// ************************************************************ smallSysFontChangeEventHandler
OSErr smallSysFontChangeEventHandler(AppleEvent *appEvent,AppleEvent *reply,
SInt32 handlerRefcon)
{
OSErr osError;
Rect portRect;
Str255 fontName, theString = "\p Current small system font is: ";
osError = doHasGotRequiredParams(appEvent);
if(osError == noErr)
{
GetWindowPortBounds(gWindowRef,&portRect);
EraseRect(&portRect);
doDrawText("\pReceived an Apple event: SMALL SYSTEM FONT CHANGED.");
GetThemeFont(kThemeSmallSystemFont,smSystemScript,fontName,NULL,NULL);
doConcatPStrings(theString,fontName);
doDrawText(theString);
// Action as required by application.
}
return osError;
}
// *************************************************************** viewsFontChangeEventHandler
OSErr viewsFontChangeEventHandler(AppleEvent *appEvent,AppleEvent *reply,
SInt32 handlerRefcon)
{
OSErr osError;
Rect portRect;
Str255 fontName, fontSizeString, theString = "\p Current views font is: ";
SInt16 fontSize;
osError = doHasGotRequiredParams(appEvent);
if(osError == noErr)
{
GetWindowPortBounds(gWindowRef,&portRect);
EraseRect(&portRect);
doDrawText("\pReceived an Apple event: VIEWS FONT CHANGED.");
GetThemeFont(kThemeViewsFont,smSystemScript,fontName,&fontSize,NULL);
doConcatPStrings(theString,fontName);
doConcatPStrings(theString,"\p ");
NumToString((SInt32) fontSize,fontSizeString);
doConcatPStrings(theString,fontSizeString);
doConcatPStrings(theString,"\p point");
doDrawText(theString);
// Action as required by application.
}
return osError;
}
// *************************************************************** showPreferencesEventHandler
OSErr showPreferencesEventHandler(AppleEvent *appEvent,AppleEvent *reply,
SInt32 handlerRefcon)
{
OSErr osError;
Rect portRect;
osError = doHasGotRequiredParams(appEvent);
if(osError == noErr)
{
GetWindowPortBounds(gWindowRef,&portRect);
EraseRect(&portRect);
doDrawText("\pReceived an Apple event: SHOW PREFERENCES.");
doDrawText("\p • I would present a Preferences... dialog now.");
}
return osError;
}
// ******************************************************************** doHasGotRequiredParams
OSErr doHasGotRequiredParams(AppleEvent *appEvent)
{
OSErr osError;
DescType returnedType;
Size actualSize;
osError = AEGetAttributePtr(appEvent,keyMissedKeywordAttr,typeWildCard,&returnedType,NULL,0,
&actualSize);
if(osError == errAEDescNotFound)
osError = noErr;
else if(osError == noErr)
osError = errAEParamMissed;
return osError;
}
// ******************************************************************************** doOpenFile
Boolean doOpenFile(FSSpec *fileSpecPtr,SInt32 index,SInt32 numberOfItems)
{
WindowRef windowRef;
gApplicationWasOpen = true;
if(index == 1)
doDrawText("\pReceived an Apple event: OPEN DOCUMENTS.");
if(numberOfItems == 1)
{
doDrawText("\p • The file to open is: ");
DrawString(fileSpecPtr->name);
doDrawText("\p • Opening titled window in response.");
}
else
{
if(index == 1)
{
doDrawText("\p • The files to open are: ");
DrawString(fileSpecPtr->name);
}
else
{
DrawString("\p and ");
DrawString(fileSpecPtr->name);
doDrawText("\p • Opening titled windows in response.");
}
}
if(windowRef = doNewWindow())
{
SetWTitle(windowRef,fileSpecPtr->name);
return true;
}
else
return false;
}
// ******************************************************************************* doPrintFile
Boolean doPrintFile(FSSpec *fileSpecPtr,SInt32 index,SInt32 numberOfItems)
{
WindowRef windowRef;
UInt32 finalTicks;
if(index == 1)
doDrawText("\pReceived an Apple event: PRINT DOCUMENTS");
if(numberOfItems == 1)
{
doDrawText("\p • The file to print is: ");
DrawString(fileSpecPtr->name);
windowRef = doNewWindow();
SetWTitle(windowRef,fileSpecPtr->name);
Delay(60,&finalTicks);
doDrawText("\p • I would present the Print dialog first and then print");
doDrawText("\p the document when the user has made his settings.");
Delay(60,&finalTicks);
doDrawText("\p • Assume that I am now printing the document.");
}
else
{
if(index == 1)
{
doDrawText("\p • The first file to print is: ");
DrawString(fileSpecPtr->name);
doDrawText("\p I would present the Print dialog for the first file");
doDrawText("\p only and use the user's settings to print both files.");
}
else
{
doDrawText("\p • The second file to print is: ");
DrawString(fileSpecPtr->name);
doDrawText("\p I am using the Print dialog settings used for the");
doDrawText("\p first file.");
}
windowRef = doNewWindow();
SetWTitle(windowRef,fileSpecPtr->name);
doDrawText("\p • Assume that I am now printing the document.");
}
if(numberOfItems == index)
{
if(!gApplicationWasOpen)
{
doDrawText("\p Since the application was not already open, I expect to");
doDrawText("\p receive a QUIT APPLICATION event when I have finished.");
}
else
{
doDrawText("\p Since the application was already open, I do NOT expect");
doDrawText("\p to receive a QUIT APPLICATION event when I have finished.");
}
Delay(180,&finalTicks);
doDrawText("\p • Finished print job.");
}
else
Delay(180, &finalTicks);
DisposeWindow(windowRef);
return true;
}
// ********************************************************************** doPrepareToTerminate
void doPrepareToTerminate(void)
{
UInt32 finalTicks;
doDrawText("\pReceived an Apple event: QUIT APPLICATION");
if(gApplicationWasOpen)
{
doDrawText("\p • I would now ask the user to save any unsaved files before");
doDrawText("\p terminating myself in response to the event.");
doDrawText("\p • Click the mouse when ready to terminate.");
while(!Button()) ;
}
else
{
doDrawText("\p • Terminating myself in response");
Delay(240,&finalTicks);
}
// If the user did not click the Cancel button in a Save dialog:
gDone = true;
}
// ******************************************************************************* doNewWindow
WindowRef doNewWindow(void)
{
WindowRef windowRef;
if(!(windowRef = GetNewCWindow(rDocWindow,NULL,(WindowRef) -1)))
doErrorAlert(eCannotOpenWindow);
return windowRef;
}
// ****************************************************************************** doMenuChoice
void doMenuChoice(SInt32 menuChoice)
{
MenuID menuID;
MenuItemIndex menuItem;
menuID = HiWord(menuChoice);
menuItem = LoWord(menuChoice);
if(menuID == 0)
return;
switch(menuID)
{
case mFile:
if(menuItem == iQuit)
gDone = true;
break;
}
HiliteMenu(0);
}
// ****************************************************************************** doErrorAlert
void doErrorAlert(SInt16 errorType)
{
Str255 errorString;
SInt16 itemHit;
GetIndString(errorString,rErrorStrings,errorType);
if(errorType < 7)
StandardAlert(kAlertCautionAlert,errorString,NULL,NULL,&itemHit);
else
{
StandardAlert(kAlertStopAlert,errorString,NULL,NULL,&itemHit);
ExitToShell();
}
}
// ******************************************************************************** doDrawText
void doDrawText(Str255 eventString)
{
RgnHandle tempRegion;
SInt16 a;
Rect portRect;
UInt32 finalTicks;
tempRegion = NewRgn();
GetWindowPortBounds(gWindowRef,&portRect);
for(a=0;a<15;a++)
{
ScrollRect(&portRect,0,-1,tempRegion);
QDFlushPortBuffer(GetWindowPort(gWindowRef),NULL);
Delay(4,&finalTicks);
}
DisposeRgn(tempRegion);
MoveTo(8,160);
DrawString(eventString);
QDFlushPortBuffer(GetWindowPort(gWindowRef),NULL);
}
// ************************************************************************** doConcatPStrings
void doConcatPStrings(Str255 targetString,Str255 appendString)
{
SInt16 appendLength;
appendLength = MIN(appendString[0],255 - targetString[0]);
if(appendLength > 0)
{
BlockMoveData(appendString+1,targetString+targetString[0]+1,(SInt32) appendLength);
targetString[0] += appendLength;
}
}
// *******************************************************************************************