This final installment illustrates how to write the event handlers and the dispatch table
Tom Thompson
Last month's column, Part 1 of this series, described how Apple Events function as a high-level means of IAC (Interapplication Communication). This month's installment will finish up the series, completing the task of adding Apple Event capabilities to your Mac application.
Part 1 left off at step two of the process, in which you build the application's dispatch table. The listing
"Building the Dispatch Table"
shows the data structure and for loop used to accomplish this. The loop calls another Apple Event Manager function,
AEIns
tallEventHandler
, with the elements of an event's class number, its ID number, and a pointer to the handler function.
It's crucial to use
NewAEEventHandlerProc()
on the pointers you supply. This sets up universal procedure pointers to these functions. This way, the Power Mac's OS can safely context-switch to the handler code's instruction set (which could be either PowerPC or 680x0). This takes care of step two.
Step three is to write the handlers themselves. The code to these is shown in the listing
"The Four Event Handlers."
Notice that we punt on handling an Open Application and Print Document event: That's because application designs vary so widely that there's no good generic code example possible.
However, these code stubs show what your application must do to respond to required Apple Events in a given situation. For our Open Application event, we merely do nothing and return a "no error" code (
noErr
), indicating that things are OK.
If your application doesn't happen to support printing, you return a code of
errAEEventNotHandled
to inform the calling application that no service is possible for that request. For a Quit Application event, all you have to do is knock down the flag that keeps the main event loop active. Upon leaving the main event loop, your application performs any housekeeping chores and exits.
The Open Document handler code shows how your application receives filenames through a high-level event. It uses a boatload of Apple Event Manager calls to pick apart the event for the information you need.
First, you call
AEGetParamDesc()
to extract the parameters from the event's data structure. This function coerces the parameters into an array known as a
descriptor list
and drops it into the buffer pointed to by
fileDesc
.
Next,
AECountItems()
determines the number of objects in the list, which is the number of files to open. The value returned by this function se
ts up the
for
loop used to collect the filenames.
Finally,
AEGetNthPtr()
gets the filenames from the descriptor list. The filenames are coerced into file-system specification records (
typeFSS
), a format used by most System 7 File Manager functions. When the filenames are in a form that's usable by the Mac OS, your application can perform the requested processing on their contents. Note that this same code can be used to get the filenames for a Print Documents Apple Event.
Finally, you need to let the Mac OS know that your application can process Apple Events. To do this, you must set the
isHighLevelEventAware
bit in the application's SIZE resource. If you fail to set this bit, the Mac OS never sends high-level events to your application. Most development environments provide a menu that lets you easily set this bit.
These snippets of code should help give you a jump-start on adding Apple Event capabilities to your Mac application. To obtain the
Appl
e Event Registry: Standard Suites
document mentioned in Part 1, which lists the structure and content of certain types of Apple Events, contact the APDA (Apple Programmer's and Developer's Association) at (716) 871-6555 or by fax at (716) 871-6511. Ask for part number R0130LLA. It costs $85.
Another excellent source of information, where all those dense technical IAC concepts are translated into something a typical programmer can comprehend, is Dave Mark's
Ultimate Mac Programming Secrets
(IDG Books, 1994). It also has a lot of code samples on CD-ROM, the best training material of all.
WHERE TO FIND
Apple Computer, Inc.
Cupertino, CA
(800) 776-2333
(408) 996-1010
fax: (408) 996-0275
// Structure for installing handlers into AE event dispatch table
struct AEinstalls
{
AEEventClass theClass;
AEEv
entID theEvent;
AEEventHandlerProcPtr theProc;
};
typedef struct AEinstalls AEinstalls;
// Build high-level event dispatch table and add our handlers to it.
// Must use static declaration so the dispatch table has file scope.
Boolean Init_AE_Events(void)
{
OSErr err;
short i;
static AEinstalls HandlersToInstall[] = // The four required Apple Events
{
{kCoreEventClass, kAEOpenApplication, Core_AE_Open_Handler},
{kCoreEventClass, kAEOpenDocuments, Core_AE_OpenDoc_Handler},
{kCoreEventClass, kAEQuitApplication, Core_AE_Quit_Handler},
{kCoreEventClass, kAEPrintDocuments, Core_AE_Print_Handler},
};
for (i = 0; i
<
LAST_HANDLER; i++)
{ // Install each handler in application dispatch table
err = AEInstallEventHandler(HandlersToInstall[i].theClass,
HandlersToInstall[i].theEvent,
NewAEEventHandlerProc(HandlersToInstall[i].theProc), 0, FALSE);
if (err) // If there was a problem, ba
il out
{
Report_Err_Message (PROBLEM_WITH_AE_HANDLER);
return FALSE;
} // end if
} // end for
return TRUE;
} // end Init_AE_Events()
// High-level open application event.
pascal OSErr Core_AE_Open_Handler(AppleEvent *messagein, AppleEvent *reply, long refIn)
{
return noErr;
} // end Core_AE_Open_Handler()
// High-level open document event
pascal OSErr Core_AE_OpenDoc_Handler(AppleEvent *messagein, AppleEvent *reply, long refIn)
{
short i;
AEDesc fileDesc;
OSErr highLevelErr;
AEKeyword ignoredKeyWord;
DescType ignoredType;
Size ignoredSize;
long numberOFiles;
FSSpec inFSS;
if (!(highLevelErr = AEGetParamDesc(messagein, keyDirectObject, typeAEList, &fileDesc)))
{
if ((highLevelErr = AECountItems(
&fileDesc, &numberOFiles)) == noErr) // Count files
{
for (i = 1; ((i
<
= numberOFiles) && (!highLevelErr)); ++i)
{
if (!(highLevelErr = AEGetNthPtr(&fileDesc, i, typeFSS, &ignoredKeyWord, &ignoredType,
(char *)&inFSS, sizeof(inFSS), &ignoredSize))) // Get each name
{
Do_Your_Stuff(&inFSS);
} // end if !highlevelErr
} // end for
} // end if == noErr
highLevelErr = AEDisposeDesc(&fileDesc); // Dispose of the copy made by AEGetParamDesc()
} // end if !highLevelErr
return highLevelErr;
} // end Core_AE_OpenDoc_Handler()
// High-level print event
pascal OSErr Core_AE_Print_Handler(AppleEvent *messagein, AppleEvent *reply, long refIn)
{
return errAEEventNotHandled; // No printing done here
} // end Core_AE_Print_Handler()
// High-level quit event
pascal OSErr Core_AE_Quit_Handler(AppleE
vent *messagein, AppleEvent *reply, long refIn)
{
guserDone = TRUE; // Tell main event loop we want to stop
return noErr;
} // Core_AE_Quit_Handler()
Tom Thompson is a BYTE senior technical editor at large with a B.S.E.E. degree from the University of Memphis. He is an Associate Apple Developer and author of Power Macintosh Programming Starter Kit (Hayden Books, 1994). You can contact him on AppleLink as "T.THOMPSON" or on the Internet or BIX at
tom_thompson@bix.com
.