Apple Developer Connection
Member Login Log In | Not a Member? Contact ADC

< Previous PageNext Page > Hide TOC

Dispatching Apple Events in Your Application

To dispatch Apple events in your application, you perform the following steps:

  1. Determine which Apple events your application will respond to and write event handler functions for those events.

  2. Call the Apple Event Manager function AEInstallEventHandler to install your handlers.

  3. Make sure your application processes Apple events correctly so that they are dispatched to the appropriate handler.

    The process for this step varies depending on how your application handles events in general.

These steps are described in the following sections.

In this section:

Determining Which Apple Events to Respond To
Installing Apple Event Handlers
Processing Apple Events


Determining Which Apple Events to Respond To

All applications that present a graphical user interface through the Human Interface Toolbox should respond to certain events sent by the Mac OS, such as the open application, open documents, and quit events. These are described in “Handling Apple Events Sent by the Mac OS.” These events can also be sent by other applications.

Your application also responds to any Apple events it has specified for working with its commands and data. To handle Apple events that your application defines, it registers handlers for the event class and event ID values you have chosen for those events. As noted, you can register wildcard values to dispatch multiple events to one or more common handlers.

Installing Apple Event Handlers

Listing 3-1 shows how your application calls AEInstallEventHandler to install an Apple event handler function. The listing assumes that you have defined the function InstallMacOSEventHandlers to install handlers for Apple events that are sent by the Mac OS—that function is shown in Listing 5-6.

Listing 3-1 also assumes you have defined the functions HandleGraphicAE and HandleSpecialGraphicAE to handle Apple events that operate on graphic objects used by your application. That function is not shown, but other event handlers are described in “Responding to Apple Events.”

Listing 3-1  Installing event handlers for various Apple events

static  OSErr   InstallAppleEventHandlers(void)
{
    OSErr   err;
 
    err = InstallMacOSEventHandlers();
    require_noerr(err, CantInstallAppleEventHandler);
 
    err = AEInstallEventHandler(kMyGraphicEventClass, kSpecialID,
            NewAEEventHandlerUPP(HandleSpecialGraphicAE), 0, false);// 1
    require_noerr(err, CantInstallAppleEventHandler);
 
    err = AEInstallEventHandler(kMyGraphicEventClass, typeWildCard,
                NewAEEventHandlerUPP(HandleGraphicAE), 0, false);// 2
    require_noerr(err, CantInstallAppleEventHandler);
 
CantInstallAppleEventHandler:
    return err;
}

In Listing 3-1, the application-defined function InstallAppleEventHandlers uses the macro require_noerr (defined in AssertMacros.h) to check the return value of each function. If an error occurs, it jumps to an error label. The function always returns an error value, which can be noErr if no error occurred.

The following descriptions apply to the numbered lines in Listing 3-1:

  1. The application-defined function HandleSpecialGraphicAE handles Apple events that deal with one specific type of graphic object supported by the application, identified by the event class kMyGraphicEventClass and event ID kSpecialID.

  2. The application-defined function HandleGraphicAE handles Apple events that deal with the application’s other graphic objects. It is installed with an event ID of typeWildCard, an Apple Event Manager constant that matches any event ID. As a result, the HandleGraphicAE function will be called to handle any received Apple event with event class kMyGraphicEventClass, except those with the event ID kSpecialID.

Both of the numbered calls to AEInstallEventHandler provide the event class, event ID, and address of an Apple event handler. The NewAEEventHandlerUPP function creates a universal procedure pointer to a handler function. The value of 0 passed for the reference constant indicates the application does not need to pass additional information to the event handler function.

Each call to AEInstallEventHandler also passes a Boolean value of false, indicating the handler should be installed in the application dispatch table, not the system dispatch table.

Processing Apple Events

How your application processes Apple events depends on how it processes events in general—whether it uses the modern Carbon event model (described in Carbon Event Manager Programming Guide), or relies on the older WaitNextEvent function. In either case, your application receives events from the operating system, some of which represent Apple events. The application dispatches these events to its Apple event handlers by calling the Apple Event Manager function AEProcessAppleEvent.

Figure 3-1 provides a conceptual view of the dispatching mechanism. It shows the flow of control between the AppleWorks application and the Apple Event Manager when the application receives an open documents event and calls AEProcessAppleEvent.


Figure 3-1  An application working with the Apple Event Manager to dispatch an open documents Apple event

An application working with the Apple Event Manager to dispatch an open documents Apple event

The AEProcessAppleEvent function takes an event of type EventRecord and looks up the Apple event it refers to in the application’s dispatch table. If it finds a handler function for the Apple event, it calls the function, passing the Apple event.

The following sections describe in detail how an application calls the AEProcessAppleEvent function.

Processing Apple Events With the Carbon Event Model

An application that uses the Carbon event model receives each Apple event as a Carbon event of type {kEventClassAppleEvent, kEventAppleEvent}. For applications that call the RunApplicationEventLoop function to process Carbon events, the AEProcessAppleEvent function is called automatically, and dispatches received Apple events as shown in Figure 3-1.

Applications that use the Carbon event model but do not call RunApplicationEventLoop must install a Carbon event handler to process Apple events. Listing 3-2 shows how you might install such a handler—in this case, named AEHandler.

Listing 3-2  Installing a Carbon event handler to handle Apple events

const EventTypeSpec kEvents[] = {{kEventClassAppleEvent, kEventAppleEvent}};
 
InstallApplicationEventHandler(NewEventHandlerUPP(AEHandler),
    GetEventTypeCount(kEvents), kEvents, 0, NULL);

Your Carbon event handler for Apple events must perform these steps:

  1. Remove the Carbon event of type {kEventClassAppleEvent, kEventAppleEvent} from the event queue before dispatching the Apple Event inside it.

    The process of removing the event from the queue triggers a synchronization with the Apple Event Manager that allows the next call to AEProcessAppleEvent to dispatch the Apple event properly. If the handler doesn’t remove the Carbon event from the queue, the application will end up dispatching the wrong Apple event.

  2. Call ConvertEventRefToEventRecord to get an EventRecord to pass to AEProcessAppleEvent.

  3. Call AEProcessAppleEvent.

  4. Return noErr to indicate the Carbon event has been handled (which does not depend on whether the dispatched Apple event is handled by the application).

Listing 3-3 shows a version of the AEHandler function.

Listing 3-3  A handler for a Carbon event that represents an Apple event

OSStatus AEHandler(EventHandlerCallRef inCaller, EventRef inEvent, void* inRefcon)
{
    Boolean     release = false;
    EventRecord eventRecord;
    OSErr       ignoreErrForThisSample;
 
    // Events of type kEventAppleEvent must be removed from the queue
    //  before being passed to AEProcessAppleEvent.
    if (IsEventInQueue(GetMainEventQueue(), inEvent))
    {
        // RemoveEventFromQueue will release the event, which will
        //  destroy it if we don't retain it first.
        RetainEvent(inEvent);
        release = true;
        RemoveEventFromQueue(GetMainEventQueue(), inEvent);
    }
 
    // Convert the event ref to the type AEProcessAppleEvent expects.
    ConvertEventRefToEventRecord(inEvent, &eventRecord);
    ignoreErrForThisSample = AEProcessAppleEvent(&eventRecord);
 
    if (release)
        ReleaseEvent(inEvent);
 
    // This Carbon event has been handled, even if no AppleEvent handlers
    //  were installed for the Apple event.
    return noErr;
}

If your application has not installed a handler for a received Apple event, the event may be handled by a handler installed by the system. For example, if your application calls RunApplicationEventLoop, a simple quit application handler is installed automatically. But if you call AEProcessAppleEvent for an event for which there is no handler installed, the event is ignored.

Processing Apple Events With WaitNextEvent

A Carbon application that uses the WaitNextEvent function, rather than the Carbon event model, receives an Apple event in its event loop as a standard event record (type EventRecord), identified by the constant kHighLevelEvent. The application passes these events to AEProcessAppleEvent, as shown in the following code listings.

Listing 3-4 shows a simplified main event loop function which continually loops, getting events and calling the HandleEvent function (in Listing 3-5) to process them.

Listing 3-4  A main event loop

static void MainEventLoop()
{
    RgnHandle       cursorRgn;
    Boolean         gotEvent;
    EventRecord     event;
 
    cursorRgn = NULL;
    while(!gQuit)
    {
        gotEvent = WaitNextEvent(everyEvent, &event, 32767L, cursorRgn);
 
        if (gotEvent)
        {
            HandleEvent(&event);
        }
    }
}

Listing 3-5 shows a standard approach for processing event records. When the value in the what field of the event record is kHighLevelEvent, the function calls AEProcessAppleEvent, which dispatches the event as shown in Figure 3-1.

Listing 3-5  A function that processes Apple events

static void HandleEvent(EventRecord *event)
{
    switch (event->what)
    {
        case mouseDown:
            HandleMouseDown(event);
            break;
 
        case keyDown:
        case autoKey:
            HandleKeyPress(event);
            break;
 
        case kHighLevelEvent:
            AEProcessAppleEvent(event);
            break;
    }
}

Listing 3-4 and Listing 3-5 are based on functions in the Xcode project AppearanceSample, located in /Developer/Examples/Carbon.



< Previous PageNext Page > Hide TOC


Last updated: 2007-10-31




Did this document help you?
Yes: Tell us what works for you.

It’s good, but: Report typos, inaccuracies, and so forth.

It wasn’t helpful: Tell us what would have helped.
Get information on Apple products.
Visit the Apple Store online or at retail locations.
1-800-MY-APPLE

Copyright © 2007 Apple Inc.
All rights reserved. | Terms of use | Privacy Notice