Apr 98 - Tips
	
Volume Number: 14 (1998)
Issue Number: 4
Column Tag: Programmer's Challenge
Apr 98 - Tips & Tidbits
by Steve Sisak
It is easier to quit an app than to close a window because the close window event requires a direct object and a position descriptor to indicate which window. Quitting an app simply requires creating a quit event and sending it.
The following code takes a valid target desc (which I'm assuming you already know how to create) and sends a close first window event to the app specified in that target desc.
The code is modified from similar code I used a while back. I may have made some errors in removing stuff or changing identifiers, but it should give you the right idea. Feel free to e-mail any questions about it.
void CloseFrontWindowOfApp( AEAddressDesc * theTargetDescPtr )
{
  AEDesc   frontWindowObjSpecifier;
  AppleEvent   event;
  AppleEvent   reply;
  OSErr  err = noErr;
//initialize descriptors 
  event.descriptorType = typeNull;
  reply.descriptorType = typeNull;
  frontWindowObjSpecifier.descriptorType = typeNull; 
  event.dataHandle = NULL;
  reply.dataHandle = NULL;
  frontWindowObjSpecifier.dataHandle = NULL;  
//create object spec for front window
  err = MyCreateFrontWindowObjSpec( &frontWindowObjSpecifier ) ;
  if ( err )
   goto CLEANUP_SetBounds;
//create apple event-- not sure if close event is in kAECoreSuite?
  err = AECreateAppleEvent( kAECoreSuite, kAEClose,
           theTargetDescPtr, kAutoGenerateReturnID,
           kAnyTransactionID, &event );
  if ( err )
   goto CLEANUP_SetBounds;
//insert direct object into ae  
  err = AEPutParamDesc( &event, keyDirectObject,             &frontWindowObjSpecifier );
  if ( err )
   goto CLEANUP_SetBounds;
//send ae
  err = AESend( &event, &reply, kAENoReply +
      kAENeverInteract +
      kAECanSwitchLayer,
      kAENormalPriority, kAEDefaultTimeout,
                kNoIdleProc, kNoFilterProc );
//dispose descriptors
CLEANUP_SetBounds:;      
  AEDisposeDesc (&event);
  AEDisposeDesc (&reply); 
  AEDisposeDesc (&frontWindowObjSpecifier); 
} //end function
OSErr MyCreateFrontWindowObjSpec( AEDesc *frontWindowObjSpec )
{
  AEDesc   emptySpecifier;
  AEDesc   positionDesc;
  long   thePosition;
  DescType propertyType;
  OSErr  err;
//initialize descriptors
  emptySpecifier.descriptorType = typeNull;
  positionDesc.descriptorType = typeNull;
  propertyDesc.descriptorType = typeNull;  
  
  emptySpecifier.dataHandle = NULL; 
  positionDesc.dataHandle = NULL;
  propertyDesc.dataHandle = NULL; 
//create objspecifier for window 1 of null container
  thePosition = 1;
  err = AECreateDesc( typeLongInteger, (Ptr)(&thePosition),
         sizeof( thePosition ), &positionDesc);
  if ( err )
   goto CLEANUP_MyCreateBoundsObjSpec;
  
  err = CreateObjSpecifier(   cWindow,
              &emptySpecifier, 
              formAbsolutePosition,
              &positionDesc, 
              false,
              frontWindowObjSpec ) ;
  if ( err )
   goto CLEANUP_MyCreateBoundsObjSpec;
  
//dispose descriptors
CLEANUP_MyCreateBoundsObjSpec:;      
  AEDisposeDesc (&windowObjSpecifier);  
  AEDisposeDesc (&positionDesc);
  return err;
}
David T. Pierson
dtp@pluto.njcc.com