Creating Windows
The Venn Diagrammer application allows the user to have multiple document windows (that is, multiple Venn diagram windows) on the desktop at the same time. Each different document window probably displays a different syllogism. As a result, the application needs some way to keep track of each window's current settings.A standard way to do this is to make use of the
refConfield in the window record. TherefConfield is reserved specifically for use by applications, which can set the field (using theSetWRefConprocedure) to any 4-byte value. Often, applications store a handle to an application-defined data structure that describes the window. This data structure is often known as a document record. Given the window pointer, you can retrieve that handle by calling theGetWRefConfunction.The sample code in this book uses a document record of type
MyDocRec(shown in Listing 6-5) to store information about the current contents of a Venn diagram window.Listing 6-5 The structure of a document record for the Venn Diagrammer application
TYPE MyDocRec = {information for a document window} RECORD figure: Integer; {the figure of the syllogism} mood: ARRAY[1..3] OF Integer; {the moods of the statements} terms: ARRAY[1..3] OF Str31; {the three terms} statusText: Str255; {most recent status message} userSolution: MyDiagramState; {user's diagram state} realSolution: MyDiagramState; {answer's diagram state} isAnswerShowing: Boolean; {is the answer showing?} isExistImport: Boolean; {stmts imply exists subject?} needsAdjusting: Boolean; {diagram needs adjusting?} END; MyDocRecPtr = ^MyDocRec; MyDocRecHnd = ^MyDocRecPtr;As you can see, the document record used by the Venn Diagrammer application contains fields that describe the current settings of the syllogism in the window, including the figure of the syllogism, the mood of each statement in the syllogism, and the terms used in those statements. The document record also contains fields that maintain information about the current appearance of the window, such as the status message most recently displayed in the window's status area (statusTextfield) and a Boolean value that indicates whether the answer is visible in the window (isAnswerShowingfield). The Venn Diagrammer application uses that Boolean value to determine how to fill in the regions in the overlapping circles. If the value ofisAnswerShowingisTRUE, the application displays the correct answer (encoded in therealSolutionfield); otherwise, the application displays the user's current answer (encoded in theuserSolutionfield).
The
- Note
- The structure of the
MyDiagramStatedata type is not shown in this book.![]()
MyDocRecdata structure also contains two other fields containing Boolean values. These specify whether the statements that make up the syllogism are to be interpreted as having existential import or not, and whether the window needs to be checked for automatic adjustment.
The Venn Diagrammer application creates a document record every time it creates a document window, and it stores a handle to the document record in the
- IMPORTANT
- If a Venn diagram window contained TextEdit fields or controls (such as radio buttons or scroll bars), the document record could be expanded to include handles to those items. Also, if a file were associated with the window, you'd want the document record to include information about that file. In a nutshell, the document record can contain all relevant information about the window that isn't contained in the window record.
![]()
refConfield of the window record. Listing 6-6 shows theDoCreateWindowroutine, which creates a new document window. This function is called when the application is first launched and whenever the user chooses the New command from the File menu.Listing 6-6 Creating a new Venn diagram window
FUNCTION DoCreateWindow: WindowPtr; VAR myPointer: Ptr; myWindow: WindowPtr; myHandle: MyDocRecHnd; BEGIN myPointer := NewPtr(sizeof(WindowRecord)); IF myPointer = NIL THEN exit(DoCreateWindow); myWindow := GetNewWindow(rVennD, myPointer, WindowPtr(-1)); IF myWindow <> NIL THEN BEGIN SetPort(myWindow); myHandle := MyDocRecHnd(NewHandleClear(sizeof(MyDocRec))); IF myHandle <> NIL THEN BEGIN HLockHi(Handle(myHandle)); {lock the data high in the heap} SetWRefCon(myWindow, LongInt(myHandle)); {attach handle to window record} DoSetWindowTitle(myWindow); {set the window title} {Define initial window settings.} WITH myHandle^^ DO BEGIN figure := 1; mood[1] := 1; mood[2] := 1; mood[3] := 1; isAnswerShowing := FALSE; isExistImport := gGiveImport; END; DoGetRandomTerms(myWindow); DoCalcAnswer(myWindow); {Position the window and display it.} DoPositionWindow(myWindow); ShowWindow(myWindow); END {IF myHandle <> NIL} ELSE BEGIN {couldn't get a data record} CloseWindow(myWindow); DisposePtr(Ptr(myWindow)); myWindow := NIL; {so pass back NIL} END; END; DoCreateWindow := myWindow; END;TheDoCreateWindowfunction first attempts to allocate space in the heap for a window record by calling the Memory Manager'sNewPtrfunction. If no space is available,DoCreateWindowexits and returnsNILto indicate that no new window was created. Otherwise,DoCreateWindowcreates the new window, whose size and type are defined in a window resource of typerVennD.
CONST rVennD = 131; {resource ID of document window}If the new window is successfully created,DoCreateWindownext tries to allocate space for a document record. Once again, if the space isn't available,DoCreateWindowtakes care to dispose of the new window and returnNILto the calling routine. Otherwise,DoCreateWindowlocks the handle to the document record high in the heap and attaches the document record to the window record by callingSetWRefCon.
The
- Note
- The document record data is locked at the top of the heap to help prevent heap fragmentation. See the chapter "Introduction to Memory Management" in Inside Macintosh: Memory for a discussion of when you need to lock data in the heap.
![]()
DoCreateWindowfunction next sets up the window's title (by calling the application-defined procedureDoSetWindowTitle) and initializes some of the fields in the document record. ThenDoCreateWindowcalls two further application-defined procedures (DoGetRandomTermsandDoCalcAnswer) to initialize thetermsfield and therealSolutionfield of the document record. (As for theuserSolutionfield, theNewHandleClearfunction, which sets all bytes in the block to 0, automatically initializes it to encode an empty diagram, according to a clever scheme.)The application-defined procedure
DoPositionWindowsets the original position of the new window according to the user's expectations and good human interface design. ThenDoCreateWindowcalls the Window Manager procedureShowWindowto display the window. TheShowWindowprocedure generates and update event for the newly displayed window, thereby causing the Venn Diagrammer application to draw the content region of the window.
- Note
- The procedure
DoPositionWindowis not defined in this book. For a discussion of how to determine the position of a new window, see the chapter "Window Manager" in Inside Macintosh: Macintosh Toolbox Essentials.![]()