Important: The information in this document is obsolete and should not be used for new development.
Zooming a Window
The zoom box allows the user to alternate quickly between two window positions and sizes: the user state and the standard state.The user state is the window size and location established by the user. If your application does not supply an initial user state, the user state is simply the size and location of the window when it was created, until the user resizes it.
The standard state is the window size and location that your application considers most convenient, considering the function of the document and the screen space available. In a word-processing application, for example, a standard-state window might show a
full page, if possible, or a page of full width and as much length as fits on the screen.
If the user changes the page size through Page Setup, the application might adjust the standard state to reflect the new page size. If your application does not define a standard state, the Window Manager automatically sets the standard state to the entire gray region on the main screen, minus a three-pixel border on all sides. (See Macintosh Human Interface Guidelines for a detailed description of how your application determines where to open and zoom windows.) The user cannot change a window's standard state.The user and standard states are stored in a record whose handle appears in the
dataHandle
field of the window record.
TYPE WStateData = RECORD userState: Rect; {size and location established by user} stdState: Rect; {size and location established by } { application} END;The Window Manager sets the initial values of theuserState
andstdState
fields when it fills in the window record, and it updates theuserState
field whenever the user resizes the window. You typically compute the standard state every time the user zooms to the standard state, to ensure that you're zooming to an appropriate location.When the user presses the mouse button with the cursor in the zoom box, the
FindWindow
function specifies whether the window is in the user state or the standard state: when the window is in the standard state,FindWindow
returnsinZoomIn
(meaning that the window is to be zoomed "in" to the user state); when the window is in the user state,FindWindow
returnsinZoomOut
(meaning that the window is to be zoomed "out" to the standard state).When
FindWindow
returns eitherinZoomIn
orinZoomOut
, your application can call theTrackBox
function to handle the highlighting of the zoom box and to determine whether the cursor is inside or outside the box when the button is released. IfTrackBox
returnsTRUE
, your application can call theZoomWindow
procedure to resize the window (after computing a new standard state). IfTrackBox
returnsFALSE
, your application doesn't need to do anything. Listing 4-9 on page 4-39 illustrates the use ofTrackBox
in an event-handling routine.Listing 4-12 illustrates an application-defined procedure,
DoZoomWindow
, which an application might call whenTrackBox
returnsTRUE
afterFindWindow
returns eitherinZoomIn
orinZoomOut
. Because the user might have moved the window to a different screen since it was last zoomed, the procedure first determines which screen contains the largest area of the window and then calculates the ideal window size for that screen before zooming the window.The screen calculations in the
DoZoomWindow
procedure depend on the routines for handling graphics devices that were introduced at the same time as Color QuickDraw. Therefore,DoZoomWindow
checks for the presence of Color QuickDraw before comparing the window to be zoomed with the graphics devices in the device list. If Color QuickDraw is not available,DoZoomWindow
assumes that it's running on a computer with a single screen.
PROCEDURE DoZoomWindow (thisWindow: windowPtr; zoomInOrOut: Integer); VAR gdNthDevice, gdZoomOnThisDevice: GDHandle; savePort: GrafPtr; windRect, zoomRect, theSect: Rect; sectArea, greatestArea: LongInt; wTitleHeight: Integer; sectFlag: Boolean; BEGIN GetPort(savePort); SetPort(thisWindow); EraseRect(thisWindow^.portRect); {erase to avoid flicker} IF zoomInOrOut = inZoomOut THEN {zooming to standard state} BEGIN IF NOT gColorQDAvailable THEN {assume a single screen and } BEGIN { set standard state to full screen} zoomRect := screenBits.bounds; InsetRect(zoomRect, 4, 4); WStateDataHandle(WindowPeek(thisWindow)^.dataHandle)^^.stdState := zoomRect; END ELSE {locate window on available graphics devices} BEGIN windRect := thisWindow^.portRect; LocalToGlobal(windRect.topLeft); {convert to global coordinates} LocalToGlobal(windRect.botRight); {calculate height of window's title bar} wTitleHeight := windRect.top - 1 - WindowPeek(thisWindow)^.strucRgn^^.rgnBBox.top; windRect.top := windRect.top - wTitleHeight; gdNthDevice := GetDeviceList; greatestArea := 0; {initialize to 0} {check window against all gdRects in gDevice list and remember } { which gdRect contains largest area of window} WHILE gdNthDevice <> NIL DO IF TestDeviceAttribute(gdNthDevice, screenDevice) THEN IF TestDeviceAttribute(gdNthDevice, screenActive) THEN BEGIN {The SectRect routine calculates the intersection } { of the window rectangle and this gDevice } { rectangle and returns TRUE if the rectangles intersect, } { FALSE if they don't.} sectFlag := SectRect(windRect, gdNthDevice^^.gdRect, theSect); {determine which screen holds greatest window area} {first, calculate area of rectangle on current device} WITH theSect DO sectArea := LongInt(right - left) * (bottom - top); IF sectArea > greatestArea THEN BEGIN greatestArea := sectArea; {set greatest area so far} gdZoomOnThisDevice := gdNthDevice; {set zoom device} END; gdNthDevice := GetNextDevice(gdNthDevice); END; {of WHILE} {if gdZoomOnThisDevice is on main device, allow for menu bar height} IF gdZoomOnThisDevice = GetMainDevice THEN wTitleHeight := wTitleHeight + GetMBarHeight; WITH gdZoomOnThisDevice^^.gdRect DO {create the zoom rectangle} BEGIN {set the zoom rectangle to the full screen, minus window title } { height (and menu bar height if necessary), inset by 3 pixels} SetRect(zoomRect, left + 3, top + wTitleHeight + 3, right - 3, bottom - 3); {If your application has a different "most useful" standard } { state, then size the zoom window accordingly.} {set up the WStateData record for this window} WStateDataHandle(WindowPeek(thisWindow)^.dataHandle)^^.stdState := zoomRect; END; END; END; {of inZoomOut} {if zoomInOrOut = inZoomIn, just let ZoomWindow zoom to user state} {zoom the window frame} ZoomWindow(thisWindow, zoomInOrOut, (thisWindow = FrontWindow)); MyResizeWindow(thisWindow); {application-defined window-sizing routine} SetPort(savePort); END; (of DoZoomWindow)If the user is zooming the window to the standard state,DoZoomWindow
calculates a new standard size and location based on the application's own considerations, the current location of the window, and the available screens. TheDoZoomWindow
procedure always places the standard state on the screen where the window is currently displayed or, if the window spans screens, on the screen containing the largest area
of the window.The bulk of the code in Listing 4-12 is devoted to determining which screen should display the window in the standard state. The sample code shown here establishes
a standard state that simply occupies the gray area on the chosen screen, minus
three pixels on all sides. Your application should establish a standard state appropriate
to its own documents. When calculating the standard state, move the window as little
as possible from the user state. If possible, anchor one corner of the standard state rectangle to one corner of the user state rectangle.If the user is zooming the window to the user state,
DoZoomWindow
doesn't have to perform any calculations, because the user state rectangle stored in the state data record should represent a valid screen location.After calculating the standard state, if necessary,
DoZoomWindow
calls theZoomWindow
procedure to redraw the window frame in the new size and location and then calls the application-defined procedureMyResizeWindow
to redraw the window's content region. Listing 4-14 on page 4-53 shows theMyResizeWindow
procedure.