Legacy Documentclose button

Important: The information in this document is obsolete and should not be used for new development.

Previous Book Contents Book Index Next

Inside Macintosh: Interapplication Communication /
Chapter 5 - Creating and Sending Apple Events


Sending an Apple Event

To send an Apple event, you first create an Apple event, add parameters and attributes to it, and then use the AESend function to send it.

When you send an Apple event, you specify various options to indicate how the server should handle the Apple event. You request a user interaction level from the server and specify whether the server can switch directly to the foreground if user interaction is needed, whether your application is willing to wait for a reply Apple event, whether reconnection is allowed, and whether your application wants a return receipt for the Apple event.

You specify these options by setting flags in the sendMode parameter for AESend. Here are the constants that represent these flags:

CONST kAENoReply        = $00000001;{client doesn't want reply}
      kAEQueueReply     = $00000002;{client wants Apple Event } 
                                    { Manager to return }
                                    { reply in event queue}
      kAEWaitReply      = $00000003;{client wants a reply and }
                                    { will give up processor}

      kAENeverInteract  = $00000010;{server application }
                                    { should not interact }
                                    { with user for this }
                                    { Apple event}
      kAECanInteract    = $00000020;{server may interact with }
                                    { user for this Apple }
                                    { event to supply } 
                                    { information}
      kAEAlwaysInteract = $00000030;{server may interact with }
                                    { user for this Apple }
                                    { event even if no }
                                    { information is required}

      kAECanSwitchLayer = $00000040;{server should come }
                                    { directly to foreground }
                                    { when appropriate}
      kAEDontReconnect  = $00000080;{don't reconnect if there }
                                    { is a PPC session closed }
                                    { error}
      kAEWantReceipt    = nReturnReceipt;{client wants return }
                                         { receipt}
      kAEDontRecord     = $00001000;{don't record this event}
      kAEDontExecute    = $00002000;{don't execute this event}
If you want your application to receive a reply Apple event, specify the kAEQueueReply or kAEWaitReply flag. If you want your application to receive the reply Apple event in its event queue, use kAEQueueReply. If you want your application to receive the reply Apple event in the reply parameter for AESend and you are willing to give up the processor while it is waiting for the reply, use kAEWaitReply. If you don't want your application to receive a reply Apple event and your application doesn't need to wait for the server to handle the Apple event, specify kAENoReply.

Note
Before the Apple Event Manager sends a reply event back to the client application, the keyAddressAttr attribute contains the address of the client application. After the client receives the reply event, the keyAddressAttr attribute contains the address of the server application.
If you specify kAENoReply or kAEQueueReply, the AESend function returns immediately after using the Event Manager to send the event. In this case, a noErr result code from AESend indicates that the Event Manager sent the Apple event; it does not mean that the server accepted or handled the Apple event.

When AESend returns, the reply parameter does not contain valid data if your application specifies kAENoReply or kAEQueueReply. The kAENoReply flag indicates that the Apple Event Manager will not return the reply Apple event to your application. The kAEQueueReply flag indicates that you want your application to receive the reply via its event queue rather than the reply parameter of AESend. If you specify kAEQueueReply, you must install a handler for the reply Apple event (event class kCoreEventClass and event ID kAEAnswer).

If you specify kAEWaitReply, the Apple Event Manager uses the Event Manager to send the event. The Apple Event Manager then calls the WaitNextEvent function on behalf of your application, causing your application to yield the processor and giving the server application a chance to receive and handle the Apple event. Your application continues to yield the processor until the server handles the Apple event or the request times out.

If you specify kAEWaitReply, you must provide an idle function. This function should process any update events, null events, operating-system events, or activate events that occur while your application is waiting for a reply. See "Writing an Idle Function," which begins on page 5-22, for sample code that shows an idle function.

You use one of the three flags--kAENeverInteract, kAECanInteract, and kAEAlwaysInteract--to specify whether the server should interact with the user when handling the Apple event. Specify kAENeverInteract if the server should not interact with the user when handling the Apple event. You might specify this constant if you don't want the user to be interrupted while the server is handling the Apple event.

Use the kAECanInteract flag if the server should interact with the user when the user needs to supply information to the server. Use the kAEAlwaysInteract flag if the server should interact with the user whenever the server normally asks a user to confirm a decision or interact in any other way, even if no additional information is needed from the user. Note that it is the responsibility of the server and client applications to agree on how to interpret the kAEAlwaysInteract flag.

If the client application does not set any one of the user interaction flags, the Apple Event Manager sets a default, depending on the location of the target of the Apple event. If the server application is on a remote computer, the Apple Event Manager sets the kAENeverInteract flag as the default. If the target of the Apple event is on the local computer, the Apple Event Manager sets the kAECanInteract flag as the default.

The server application should call AEInteractWithUser if it needs to interact with the user. If both the client and the server allow user interaction, the Apple Event Manager attempts to bring the server to the foreground if it is not already the foreground process. If both the kAECanSwitchLayer and the kAEWaitReply flags are set, and if the client application is the active application on the local computer, the Apple Event Manager brings the server application directly to the front. Otherwise, the Apple Event Manager posts a notification request asking the user to bring the server application to the front, regardless of whether the kAECanSwitchLayer flag is set. This ensures that the user will not be interrupted by an unexpected application switch.

You should specify the kAECanSwitchLayer flag only when the client and server applications reside on the same computer. In general, you should not set this flag if it would be confusing or inconvenient to the user for the server application to come to the front unexpectedly. This flag is ignored if you are sending an Apple event to a remote computer.

Specify the kAEDontReconnect flag if the Apple Event Manager should not reconnect if it receives a session closed error from the PPC Toolbox. If you don't set this flag, the Apple Event Manager automatically attempts to reconnect and reestablish the session.

Specify the kAEWantReceipt flag if your application wants notification that the server application has accepted the Apple event. If you specify this flag, your application receives a return receipt as a high-level event.

If you specify the kAEWantReceipt flag and the server application does not accept the Apple event within the time specified by the timeOutInTicks parameter to AESend, the AESend function returns a timeout error. Note that AESend also returns a timeout error if your application sets the kAEWaitReply flag and does not receive the reply Apple event within the time specified by the timeOutInTicks parameter.

Specify the kAEDontRecord flag if your application is sending an Apple event to itself that you don't want to be recorded. When Apple event recording has been turned on, every event that your application sends to itself will be automatically recorded by the Apple Event Manager except those sent with the kAEDontRecord flag set.

Specify the kAEDontExecute flag if your application is sending an Apple event to itself for recording purposes only--that is, if you want the Apple Event Manager to send a copy of the event to the recording process but you do not want your application actually to receive the event. (For more information about when to use the kAEDontExecute flag, see the chapter "Recording Apple Events" in this book.)

Listing 5-4 illustrates how to send a Multiply event (an imaginary Apple event for multiplying two long integers). It first creates an Apple event, adds parameters containing the numbers to multiply, then sends it, specifying various options. It also illustrates how to handle the reply Apple event that contains the result.

Note
If you want to send Apple events, your application must set flags in its 'SIZE' resource indicating that it can handle high-level events, and it must provide handlers for the required Apple events. See "Accepting an Apple Event" on page 4-5 for information on setting the appropriate flags in the 'SIZE' resource and "Handling the Required Apple Events" on page 4-11 for information on supporting the required Apple events.
Listing 5-4 Sending an Apple event

FUNCTION MySendMultiplyEvent (serverAddress: AEAddressDesc;
                              firstOperand: LongInt; secondOperand: LongInt;
                              VAR replyResultLongInt: LongInt): OSErr;
CONST
   kArithmeticClass  =  'ARTH';  {event class for arithmetic }
                                 { Apple events}
   kMultiplyEventID  =  'MULT';  {event ID for Multiply event}
   keyMultOperand1   =  'OPN1';  {keyword for first parameter}
   keyMultOperand2   =  'OPN2';  {keyword for second parameter}
VAR
   theAppleEvent:    AppleEvent;
   reply:            AppleEvent;
   returnedType:     DescType;
   actualSize:       LongInt;
   myErr:            OSErr;
   ignoreErr:        OSErr; 
   errStr:           Str255;
   errNumber:        LongInt;
BEGIN
   myErr := AECreateAppleEvent(kArithmeticClass, kMultiplyEventID, 
                               serverAddress, kAutoGenerateReturnID,
                               kAnyTransactionID, theAppleEvent);
   IF myErr = noErr THEN 
      {add the first operand}
      myErr := AEPutParamPtr(theAppleEvent, keyMultOperand1, 
                             typeLongInteger, @firstOperand, 
                             SizeOf(firstOperand));
   {add the second operand with the proper keyword}
   IF myErr = noErr THEN
      myErr := AEPutParamPtr(theAppleEvent, keyMultOperand2, 
                             typeLongInteger, @secondOperand, 
                             SizeOf(secondOperand));

   IF myErr = noErr THEN
      myErr := AESend(theAppleEvent, reply, kAEWaitReply + kAENeverInteract,
                    kAENormalPriority, 120, @MyIdleFunction, NIL);
   IF myErr = noErr THEN {Apple event successfully sent}
   BEGIN    {Check whether it was successfully handled-- }
            { get result code returned by the server's handler}
      myErr := AEGetParamPtr(reply, keyErrorNumber, typeLongInteger, 
                             returnedType, @errNumber, SizeOf(errNumber), 
                             actualSize);

      IF (myErr = errAEDescNotFound) OR (errNumber = noErr) THEN
      {if keyErrorNumber doesn't exist or server returned noErr }
      { then the Apple event was successfully handled--the reply Apple }
      { event contains the result in the direct parameter}
         myErr := AEGetParamPtr(reply, keyDirectObject, typeLongInteger, 
                                returnedType, @replyResultLongInt,
                                SizeOf(replyResultLongInt), actualSize)
      ELSE
      BEGIN    {server returned an error, so get error string}
         myErr := AEGetParamPtr(reply, keyErrorString, typeChar, 
                                returnedType, @errStr[1], SizeOf(errStr)-1, 
                                actualSize);
         IF myErr = noErr THEN
         BEGIN
            IF actualSize > 255 THEN
               actualSize := 255;
            errStr[0] := chr(actualSize);
            MyDisplayError(errStr);
         END;
      END;
   ignoreErr := AEDisposeDesc(reply);
   END
   ELSE
   BEGIN
      {the Apple event wasn't successfully dispatched, }
      { the request timed out, the user canceled, or other error} 
   END;
   ignoreErr := AEDisposeDesc(theAppleEvent);
   MySendMultiplyEvent := myErr;
END;
The code in Listing 5-4 first creates an Apple event with kArithmeticClass as the event class and kMultiplyEventID as the event ID. It also specifies the server of the Apple event. See "Specifying a Target Address" on page 5-10 for information on specifying a target address and "Creating an Apple Event," which begins on page 5-3, for more information on creating an Apple event.

The Multiply event shown in Listing 5-4 contains two parameters, each specifying a number to multiply. See "Adding Parameters to an Apple Event" on page 5-5 for examples of how to specify the parameters for the AEPutParamPtr function.

After adding the parameters to the event, the code uses AESend to send the event. The first parameter to AESend specifies the Apple event to send--in this example, the Multiply event. The next parameter specifies the reply Apple event.

This example specifies kAEWaitReply in the third parameter, indicating that the client is willing to yield the processor for the specified timeout value (120 ticks, or 2 seconds). The kAENeverInteract flag indicates that the server should not interact with the user when processing the Apple event. The fourth parameter specifies that the Multiply event is to be sent using normal priority (that is, placed at the end of the event queue). You can specify the kAEHighPriority flag to place the event in the front of the event queue, but this is not usually recommended.

The next to last parameter specifies the address of an idle function. If you specify kAEWaitReply, you must provide an idle function. This function should process any update events, null events, operating-system events, or activate events that occur while your application is waiting for a reply. See "Writing an Idle Function," which begins on page 5-22, for sample code that shows an idle function.

The last parameter to AESend specifies a filter function. You can supply a filter function to filter high-level events that your application may receive while waiting for a reply Apple event. You can specify NIL for this parameter if you do not need to filter high-level events while waiting for a reply. See "Writing a Reply Filter Function" on page 5-24 for more information.

If you specify kAEWaitReply, a noErr result code from AESend indicates that the Apple event was sent successfully, not that the server has completed the requested action successfully. Therefore, you should find out whether a result code was returned from the handler by checking the reply Apple event for the existence of either the keyErrorNumber or keyErrorString parameter. If the keyErrorNumber parameter does not exist or contains the noErr result code, you can use AEGetParamPtr to get the parameter you're interested in from the reply Apple event.

The MySendMultiplyEvent function in Listing 5-4 checks the function result of AESend. If it is noErr, MySendMultiplyEvent checks the keyErrorNumber parameter of the reply Apple event to determine whether the server successfully handled the Apple event. If this parameter exists and indicates that an error occurred, MySendMultiplyEvent gets the error string out of the keyErrorString parameter. Otherwise, the server performed the request, and the reply Apple event contains the answer to the multiplication request.

When you have finished using the Apple event specified in the AESend function and no longer need the reply Apple event, you must dispose of both the original event and the reply by calling the AEDisposeDesc function.

IMPORTANT
If your application sends Apple events to itself using a typeProcessSerialNumber address descriptor record with the lowLongOfPSN field set to kCurrentProcess, the Apple Event Manager jumps directly to the appropriate Apple event handler without going through the normal event-processing sequence. For this reason, your application will not appear to run more slowly when it sends Apple events to itself. For more information, see "Addressing an Apple Event for Direct Dispatching" on page 5-13.

Subtopics
Dealing With Timeouts
Writing an Idle Function
Writing a Reply Filter Function

Previous Book Contents Book Index Next

© Apple Computer, Inc.
7 JUL 1996