Legacy Documentclose button

Important: The information in this document is obsolete and should not be used for new development.

Previous Book Contents Book Index Next

Inside Macintosh: Macintosh Toolbox Essentials /
Chapter 4 - Window Manager / Using the Window Manager


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 the userState and stdState fields when it fills in the window record, and it updates the userState 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 returns inZoomIn (meaning that the window is to be zoomed "in" to the user state); when the window is in the user state, FindWindow returns inZoomOut (meaning that the window is to be zoomed "out" to the standard state).

When FindWindow returns either inZoomIn or inZoomOut, your application can call the TrackBox 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. If TrackBox returns TRUE, your application can call the ZoomWindow procedure to resize the window (after computing a new standard state). If TrackBox returns FALSE, your application doesn't need to do anything. Listing 4-9 on page 4-39 illustrates the use of TrackBox in an event-handling routine.

Listing 4-12 illustrates an application-defined procedure, DoZoomWindow, which an application might call when TrackBox returns TRUE after FindWindow returns either inZoomIn or inZoomOut. 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.

Listing 4-12 Zooming a window

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. The DoZoomWindow 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 the ZoomWindow procedure to redraw the window frame in the new size and location and then calls the application-defined procedure MyResizeWindow to redraw the window's content region. Listing 4-14 on page 4-53 shows the MyResizeWindow procedure.


Previous Book Contents Book Index Next

© Apple Computer, Inc.
11 JUL 1996