Important: The information in this document is obsolete and should not be used for new development.
Factoring the Quit Command and the New Command
This section demonstrates how to factor two File menu commands: Quit and New.When the user chooses a menu command, an application first determines which one was chosen and then performs the action associated with that command. For example, when a user chooses Quit from the File menu, an application that is not factored simply calls an application-defined
DoQuit
routine. Because Quit Application is one of the required Apple events, it is relatively easy for most applications that support Apple events to factor the code that responds to the Quit command.After a factored application has determined that the user has chosen the Quit command, it sends the Quit Application event to itself by calling its
MyDoMenuQuit
routine.
PROCEDURE MyDoMenuQuit; VAR myErr: OSErr; BEGIN myErr := MySendAEQuit(kAEAskUser); {handle any errors} END;TheMyDoMenuQuit
routine in turn calls theMySendAEQuit
routine shown in
Listing 9-1, which creates the Quit Application event and sends it.Listing 9-1 A function used by a factored application to send itself a Quit Application event
FUNCTION MySendAEQuit (saveOpt: DescType): OSErr; VAR myAppleEvent, defReply: AppleEvent; myErr, ignoreErr: OSErr; BEGIN {create Quit event} myErr := AECreateAppleEvent(kCoreEventClass, kAEQuitApplication, gSelfAddrDesc, kAutoGenerateReturnID, kAnyTransactionID, myAppleEvent); IF myErr = noErr THEN {add optional parameter that specifies whether this app } { should prompt user if window is dirty} myErr := AEPutParamPtr(myAppleEvent, keyAESaveOptions, typeEnumerated, @saveOpt, SizeOf(saveOpt)); IF myErr = noErr THEN {send event} myErr := AESend(myAppleEvent, defReply, kAENoReply+kAEAlwaysInteract, kAENormalPriority, kAEDefaultTimeOut, NIL, NIL); MySendAEQuit := myErr; ignoreErr := AEDisposeDesc(myAppleEvent); END;The input to theMySendAEQuit
routine is a constant that indicates whether to save dirty windows without asking the user (kAEYes
), quit without saving dirty windows (kAENo
), or ask the user whether each dirty window should be saved (kAEAskUser
). In this example, the constantkAEAskUser
passed to theMySendAEQuit
routine indicates that the user will be asked whether each dirty window should be saved.After the application receives the Quit Application event, the
MyHandleQuit
handler shown in Listing 9-2 performs all the actions associated with that event, such as saving any open documents. (Note that your application should call theExitToShell
procedure from the main event loop, not from your handler for the Quit Application event.)Listing 9-2 A routine used by a factored application to handle a Quit Application event
FUNCTION MyHandleQuit (theAppleEvent, reply: AppleEvent; handlerRefcon: LongInt): OSErr; VAR userCanceled: Boolean; saveOpt, returnedType: DescType; actSize: Size; myErr: OSErr; BEGIN {check for missing required parameters} myErr := MyGotRequiredParams(theAppleEvent); IF myErr = noErr THEN BEGIN {pick up optional save parameter} saveOpt := kAEAskUser; {the default} myErr := AEGetParamPtr(theAppleEvent, keyAESaveOptions, typeEnumerated, returnedType, @saveOpt, SizeOf(saveOpt), actSize); IF myErr = errAEDescNotFound THEN myErr := noErr; MyHandleQuit := myErr; IF myErr = noErr THEN BEGIN userCanceled := MyPrepareToTerminate(saveOpt); IF userCanceled THEN MyHandleQuit := kUserCanceled; END; END ELSE MyHandleQuit := myErr; END;The handler in Listing 9-2 calls another function supplied by the application, theMyPrepareToTerminate
function. When the value of the optional parameter that specifies how to deal with dirty windows equalskAEAskUser
, this function asks the user whether to save each dirty window and returns a Boolean value that indicates whether the user canceled the Quit request. It also responds appropriately to the other possible values of the optional parameter.If recording has been turned on for a scripting component (for example, after a user clicks the Record button in the Script Editor application) and the user quits the application, the Apple Event Manager automatically sends the scripting component a copy of the Quit Application event sent by the
MySendAEQuit
routine. The scripting component records the event in a compiled script. When a user executes the recorded script, the scripting component sends the same Quit Application event to the application, which calls theMyHandleQuit
function and responds to the event just as if the user had chosen Quit from the File menu.After you have factored the commands associated with required Apple events for an existing application, you can move on to the other commands in the File menu, such as New. After a factored application has determined that the user has chosen New, it calls its
MyDoMenuNew
routine, which sends the Create Element event to the application.
PROCEDURE MyDoMenuNew; VAR myErr := OSErr; BEGIN myErr := MySendAECreateElement(gNullDesc, cDocument); {handle any errors} END;The container for the new element is the application's default container, specified by a null descriptor record, and the desired class iscDocument
. TheMyDoMenuNew
routine in turn calls theMySendAECreateElement
routine shown in Listing 9-3, which creates the Apple event and sends it.Listing 9-3 A routine used by a factored application to send itself a Create Element event
FUNCTION MySendAECreateElement (cont: AEDesc; elemClass: DescType): OSErr; VAR myAppleEvent, defReply: AppleEvent; myErr, ignoreErr: OSErr; BEGIN {create Create Element event} myErr := AECreateAppleEvent(kCoreEventClass, kAECreateElement, gSelfAddrDesc, kAutoGenerateReturnID, kAnyTransactionID, myAppleEvent); IF myErr = noErr THEN {add parameter that specifies insertion location for the } { new element} myErr := AEPutParamDesc(myAppleEvent,keyAEInsertHere,cont); IF myErr = noErr THEN {add parameter that specifies new element's object class} myErr := AEPutParamPtr(myAppleEvent, keyAEObjectClass, typeType, @elemClass, SizeOf(elemClass)); IF myErr = noErr THEN {send the event} myErr := AESend(myAppleEvent, defReply, kAENoReply+kAECanInteract, kAENormalPriority, kAEDefaultTimeOut, NIL, NIL); MySendAECreateElement := myErr; ignoreErr := AEDisposeDesc(myAppleEvent); {must dispose of } { event} END;For the purposes of this example, the routine shown in Listing 9-3 sends only the required parameters and can only create a new active window with the default name. After the application receives the Create Element event, itsMyHandleCreateElement
handler performs the requested action, as shown in Listing 9-4. In this case, it creates a new active window with a default title.Listing 9-4 The Create Element event handler for a factored application
FUNCTION MyHandleCreateElement (theAppleEvent: AppleEvent; reply: AppleEvent; handlerRefCon: LongInt): OSErr; VAR myCont: AEDesc; returnedType, newElemClass: DescType; actSize: Size; contClass: DescType; window: WindowPtr; myErr: OSErr; BEGIN {get the parameters out of the event} {first get the direct parameter, which specifies insertion } { location for new window--that is, frontmost window} myCont.dataHandle := NIL; myErr := AEGetParamDesc(theAppleEvent, keyAEInsertHere, typeWildCard, myCont); IF myErr = noErr THEN {get the other required parameter, which specifies class } { cDocument when MyHandleCreateElement creates a new window} myErr := AEGetParamPtr(theAppleEvent, keyAEObjectClass, typeType, returnedType, @newElemClass, SizeOf(newElemClass), actSize); IF myErr = noErr THEN myErr := MyGotRequiredParams(theAppleEvent); MyHandleCreateElement := myErr; IF myErr = noErr THEN BEGIN {check container and class, just to make sure} IF (myCont.descriptorType <> typeNull) OR (newElemClass <> cDocument) THEN MyHandleCreateElement := kWrongContainerOrElement ELSE {MyNewWindow creates a new window with a default name } { and returns a pointer to it in the window parameter} MyHandleCreateElement := MyNewWindow(window); END; myErr := AEDisposeDesc(myCont); {if your app sends a reply in response to the Create Element } { event, then set up the reply event as appropriate} END;If recording has been turned on for a scripting component (for example, after a user clicks the Record button in the Script Editor application), the Apple Event Manager automatically sends the scripting component a copy of the Create Element event sent by theMySendAECreateElement
routine. The scripting component records the Apple event as a statement in a compiled script. When a user executes the recorded script, the scripting component sends the same Create Element event to the application, which calls itsMyHandleCreateElement
handler and responds to the event just as if the user had chosen New from the File menu.