Important: The information in this document is obsolete and should not be used for new development.
Closing a File
In most cases, your application closes a file after a user clicks in a window's close box or chooses the Close command in the File menu. The Close menu command should be active only when there is actually an active window on the desktop. If there is an active window, you need to determine whether it belongs to your application; if so, you need to handle dialog windows and document windows differently, as illustrated in Listing 1-15.Listing 1-15 Handling the Close menu command
FUNCTION DoCloseCmd: OSErr; VAR myWindow: WindowPtr; myData: MyDocRecHnd; myErr: OSErr; BEGIN myErr := FALSE; myWindow := FrontWindow; {get window to be closed} CASE MyGetWindowType(myWindow) OF kDAWindow: CloseDeskAcc(WindowPeek(myWindow)^.windowKind); kMyModelessDialog: HideWindow(myWindow); {for dialogs, hide the window} kMyDocWindow: BEGIN myData := MyDocRecHnd(GetWRefCon(myWindow)); myErr := DoCloseFile(myData); IF myErr = noErr THEN DisposeWindow(myWindow); END; OTHERWISE ; END; DoCloseCmd := myErr; END;TheDoCloseCmd
function determines the type of the frontmost window by calling the application-defined functionMyGetWindowType
. (See the chapter "Window Manager" in Inside Macintosh: Macintosh Toolbox Essentials for a definition ofMyGetWindowType
.) If the window to be closed is a window belonging to a desk accessory,DoCloseCmd
closes the desk accessory. If the window to be closed is a dialog window, this procedure just hides the window. If the window to be closed is a document window,DoCloseCmd
retrieves its document record handle and calls bothDoCloseFile
(defined in
Listing 1-16) andDisposeWindow
. Before you close the file associated with a
window, you should check whether the contents of the window have changed since
the last time the document was saved. If so, you should ask the user whether to save those changes. Listing 1-16 illustrates one way to do this.
FUNCTION DoCloseFile (myData: MyDocRecHnd): OSErr; VAR myErr: OSErr; myDialog: DialogPtr; {pointer to modal dialog box} myItem: Integer; {item selected in alert box} myPort: GrafPtr; {the original graphics port} CONST kSaveChangesDialog = 129; {resource of Save changes dialog} BEGIN IF myData^^.windowDirty THEN {see whether window is dirty} BEGIN myItem := CautionAlert(kSaveChangesDialog, NIL); IF myItem = iCancel THEN{user clicked Cancel} BEGIN DoCloseFile := usrCanceledErr; Exit(DoCloseFile); END; IF myItem = iSave THEN myErr := DoSaveCmd; END; IF myData^^.fileRefNum <> 0 THEN BEGIN myErr := FSClose(myData^^.fileRefNum); IF myErr = noErr THEN BEGIN myErr := FlushVol(NIL, myData^^.fileFSSpec.vRefNum); myData^^.fileRefNum := 0; {clear the file reference number} END; END; {Dispose of TextEdit record and controls here (code omitted).} DisposeHandle(Handle(myData)); {dispose of document record} DoCloseFile := myErr; END;If the document is an existing file that has not been changed since it was last saved, your application can simply call theFSClose
function. This routine writes to disk any unwritten data remaining in the volume buffer. TheFSClose
function also updates the information maintained on the volume for that file and removes the access path. The information about the file is not actually written to the disk, however, until the volume is flushed, ejected, or unmounted. To keep the file information current, it's a good idea to follow each call toFSClose
with a call to theFlushVol
function.If the contents of an existing file have been changed, or if a new file is being closed for the first time, your application can call the Dialog Manager routine
CautionAlert
(specifying a resource ID of an'ALRT'
template) to ask the user whether or not to save the changes. If the user decides not to save the file, you can just callFSClose
and dispose of the window. Otherwise,DoCloseFile
calls theDoSaveCmd
function to save the file to disk.