TweetFollow Us on Twitter

MACINTOSH C CARBON

Demonstration Program Windows1

Goto Contents

// *******************************************************************************************
// Windows1.c                                                              CLASSIC EVENT MODEL
// *******************************************************************************************
// 
// This program:
//
// o  Allows the user to open any number of kWindowFullZoomGrowDocumentProc windows, up to the
//    maximum specified by the constant assigned to the symbolic name kMaxWindows, using the 
//    File menu Open Command or its keyboard equivalent.
//
// o  Allows the user to close opened windows using the close box/button, the File menu Close
//    command or the Close command's keyboard equivalent.
//
// o  Adds menu items representing each window to a Windows menu as each window is opened.
//    (A keyboard equivalent is included in each menu item for windows 1 to 9.)
//
// o  Deletes menu items from the Windows menu as each window is closed.
//
// o  Fills each window with a plain colour pattern as a means of proving, for demonstration
//    purposes, the window update process.
//
// o  Facilitates activation of a window by mouse selection.
//
// o  Facilitates activation of a window by Windows menu selection.
//
// o  Correctly performs all dragging, zooming and sizing operations.
//
// o  On Mac OS 8/9, demonstrates the provision of balloon help for static windows.
//
// The program utilises the following resources:
//
// o  A 'plst' resource.
//
// o  An 'MBAR' resource, and 'MENU' resources for Apple/Application, File, Edit and Windows 
//    menus, (preload non-purgeable).  
//
// o  A 'WIND' resource (purgeable) (initially not visible).  
//
// o  A 'STR#' resource containing error strings and the window title (purgeable).
//
// o  An 'hrct' resource and an 'hwin' resource for balloon help (both purgeable).
//
// o  Ten 'ppat' (pixel pattern) resources (purgeable), which are used to draw a plain colour
//    pattern in the windows.
//
// o  A 'SIZE' resource with the acceptSuspendResumeEvents, canBackground, 
//    doesActivateOnFGSwitch, and isHighLevelEventAware flags set.
//
// *******************************************************************************************

// .................................................................................. includes

#include <Carbon.h>

// ................................................................................... defines

#define rMenubar          128
#define mAppleApplication 128
#define  iAbout           1
#define mFile             129
#define  iNew             1
#define  iClose           4
#define  iQuit            12
#define mWindows          131
#define rNewWindow        128
#define rStringList       128
#define  sUntitled        1
#define  eMaxWindows      2
#define  eFailWindow      4
#define  eFailMenus       5
#define  eFailMemory      6
#define rPixelPattern     128
#define kMaxWindows       10
#define kScrollBarWidth   15
#define MAX_UINT32        0xFFFFFFFF
#define MIN(a,b)          ((a) < (b) ? (a) : (b))
#define topLeft(r)        (((Point *) &(r))[0])

// .......................................................................... global variables

Boolean   gRunningOnX = false;
Boolean   gDone;
SInt32    gUntitledWindowNumber = 0;
SInt32    gCurrentNumberOfWindows = 0;
WindowRef gWindowRefArray[kMaxWindows + 2];

// ....................................................................... function prototypes

void    main                      (void);
void    doPreliminaries           (void);
OSErr   quitAppEventHandler       (AppleEvent *,AppleEvent *,SInt32);
void    eventLoop                 (void);
void    doEvents                  (EventRecord *);
void    doMouseDown               (EventRecord *);
void    doUpdate                  (EventRecord *);
void    doUpdateWindow            (EventRecord *);
void    doActivate                (EventRecord *);
void    doActivateWindow          (WindowRef,Boolean);
void    doOSEvent                 (EventRecord *);
void    doMenuChoice              (SInt32);
void    doFileMenu                (MenuItemIndex);
void    doWindowsMenu             (MenuItemIndex);
void    doNewWindow               (void);
void    doCloseWindow             (void);
void    doInvalidateScrollBarArea (WindowRef);
void    doConcatPStrings          (Str255,Str255);
void    doErrorAlert              (SInt16);
Boolean eventFilter               (DialogPtr,EventRecord *,SInt16 *);

// ************************************************************************************** main

void  main(void)
{
  MenuBarHandle menubarHdl;
  SInt32        response;
  MenuRef       menuRef;
  SInt16        a;

  // ........................................................................ do preliminaries

  doPreliminaries();

  // ............................................................... set up menu bar and menus
  
  menubarHdl = GetNewMBar(rMenubar);
  if(menubarHdl == NULL)
    doErrorAlert(eFailMenus);
  SetMenuBar(menubarHdl);
  DrawMenuBar();

  Gestalt(gestaltMenuMgrAttr,&response);
  if(response & gestaltMenuMgrAquaLayoutMask)
  {
    menuRef = GetMenuRef(mFile);
    if(menuRef != NULL)
    {
      DeleteMenuItem(menuRef,iQuit);
      DeleteMenuItem(menuRef,iQuit - 1);
    }

    gRunningOnX = true;
  }

  // ....................................................... initialize window reference array

  for(a=0;a<kMaxWindows+2;a++)
    gWindowRefArray[a] = NULL;

  // ......................................................................... enter eventLoop

  eventLoop();
}

// *************************************************************************** doPreliminaries

void  doPreliminaries(void)
{
  OSErr osError;

  MoreMasterPointers(224);
  InitCursor();
  FlushEvents(everyEvent,0);

  osError = AEInstallEventHandler(kCoreEventClass,kAEQuitApplication,
                            NewAEEventHandlerUPP((AEEventHandlerProcPtr) quitAppEventHandler),
                            0L,false);
  if(osError != noErr)
    ExitToShell();
}

// **************************************************************************** doQuitAppEvent

OSErr  quitAppEventHandler(AppleEvent *appEvent,AppleEvent *reply,SInt32 handlerRefcon)
{
  OSErr    osError;
  DescType returnedType;
  Size     actualSize;

  osError = AEGetAttributePtr(appEvent,keyMissedKeywordAttr,typeWildCard,&returnedType,NULL,0,
                              &actualSize);

  if(osError == errAEDescNotFound)
  {
    gDone = true;
    osError = noErr;
  } 
  else if(osError == noErr)
    osError = errAEParamMissed;

  return osError;
}

// ********************************************************************************* eventLoop

void  eventLoop(void)
{
  EventRecord eventStructure;

  gDone = false;

  while(!gDone)
  {
    if(WaitNextEvent(everyEvent,&eventStructure,MAX_UINT32,NULL))
      doEvents(&eventStructure);
  }
}

// ********************************************************************************** doEvents

void  doEvents(EventRecord *eventStrucPtr)
{
  switch(eventStrucPtr->what)
  {
    case kHighLevelEvent:
      AEProcessAppleEvent(eventStrucPtr);
      break;

    case mouseDown:
      doMouseDown(eventStrucPtr);
      break;

    case keyDown:
      if((eventStrucPtr->modifiers & cmdKey) != 0)
        doMenuChoice(MenuEvent(eventStrucPtr));
      break;

    case updateEvt:
      doUpdate(eventStrucPtr);
      break;

    case activateEvt:
      doActivate(eventStrucPtr);
      break;

    case osEvt:
      doOSEvent(eventStrucPtr);
      break;
  }
}

// ******************************************************************************* doMouseDown

void  doMouseDown(EventRecord *eventStrucPtr)
{
  WindowRef      windowRef;
  WindowPartCode partCode, zoomPart;
  BitMap         screenBits;
  Rect           constraintRect, mainScreenRect;
  Point          standardStateHeightAndWidth;

  partCode = FindWindow(eventStrucPtr->where,&windowRef);

  switch(partCode)
  {
    case inMenuBar:
      doMenuChoice(MenuSelect(eventStrucPtr->where));
      break;

    case inContent:
      if(windowRef != FrontWindow())
        SelectWindow(windowRef);
      break;

    case inDrag:
      DragWindow(windowRef,eventStrucPtr->where,NULL);
      break;

    case inGoAway:
      if(TrackGoAway(windowRef,eventStrucPtr->where) == true)
        doCloseWindow();
      break;

    case inGrow:
      constraintRect.top   = 75; 
      constraintRect.left = 205;
      constraintRect.bottom = constraintRect.right = 32767;
      doInvalidateScrollBarArea(windowRef);
      ResizeWindow(windowRef,eventStrucPtr->where,&constraintRect,NULL);
      doInvalidateScrollBarArea(windowRef);
      break;

    case inZoomIn:
    case inZoomOut:
      mainScreenRect = GetQDGlobalsScreenBits(&screenBits)->bounds;
      standardStateHeightAndWidth.v = mainScreenRect.bottom;
      standardStateHeightAndWidth.h = 460;

      if(IsWindowInStandardState(windowRef,&standardStateHeightAndWidth,NULL))
        zoomPart = inZoomIn;
      else
        zoomPart = inZoomOut;

      if(TrackBox(windowRef,eventStrucPtr->where,partCode))
        ZoomWindowIdeal(windowRef,zoomPart,&standardStateHeightAndWidth);
      break;
  }
}

// ********************************************************************************** doUpdate

void  doUpdate(EventRecord *eventStrucPtr)
{
  WindowRef windowRef;

  windowRef = (WindowRef) eventStrucPtr->message;

  BeginUpdate(windowRef);

  SetPortWindowPort(windowRef);
  doUpdateWindow(eventStrucPtr);

  EndUpdate(windowRef);
}

// **************************************************************************** doUpdateWindow

void  doUpdateWindow(EventRecord *eventStrucPtr)
{
  WindowRef    windowRef;
  RgnHandle    visibleRegionHdl;
  Rect         theRect;
  SInt32       windowRefCon;
  PixPatHandle pixpatHdl;
  RGBColor     whiteColour = { 0xFFFF,0xFFFF,0xFFFF };
  SInt16       a;
  
  windowRef = (WindowRef) eventStrucPtr->message;

  visibleRegionHdl = NewRgn();
  GetPortVisibleRegion(GetWindowPort(windowRef),visibleRegionHdl);
  EraseRgn(visibleRegionHdl);
  DisposeRgn(visibleRegionHdl);

  GetWindowPortBounds(windowRef,&theRect);
  theRect.right  -= kScrollBarWidth;
  theRect.bottom -= kScrollBarWidth;

  windowRefCon = GetWRefCon(windowRef);
  pixpatHdl = GetPixPat(rPixelPattern + windowRefCon);
  FillCRect(&theRect,pixpatHdl);
  DisposePixPat(pixpatHdl);

  DrawGrowIcon(windowRef);    

  RGBForeColor(&whiteColour);
  TextSize(10);

  if(!gRunningOnX)
  {
    for(a=0;a<2;a++)
    {
      SetRect(&theRect,a*90+10,10,a*90+90,33);
      FrameRect(&theRect);
      MoveTo(a*90+18,25);

      DrawString("\pHot Rectangle");
    }
  }
}

// ******************************************************************************** doActivate

void  doActivate(EventRecord *eventStrucPtr)
{
  WindowRef windowRef;
  Boolean   becomingActive;

  windowRef = (WindowRef) eventStrucPtr->message;

  becomingActive = ((eventStrucPtr->modifiers & activeFlag) == activeFlag);

  doActivateWindow(windowRef,becomingActive);
}

// ************************************************************************** doActivateWindow

void  doActivateWindow(WindowRef windowRef,Boolean becomingActive)
{
  MenuRef windowsMenu;
  SInt16  menuItem, a = 1;

  windowsMenu = GetMenuRef(mWindows);

  while(gWindowRefArray[a] != windowRef)
    a++;
  menuItem = a;
  
  if(becomingActive)
    CheckMenuItem(windowsMenu,menuItem,true);
  else
    CheckMenuItem(windowsMenu,menuItem,false);
    
  DrawGrowIcon(windowRef);
}

// ********************************************************************************* doOSEvent

void  doOSEvent(EventRecord *eventStrucPtr)
{
  switch((eventStrucPtr->message >> 24) & 0x000000FF)
  {
    case suspendResumeMessage:
      if((eventStrucPtr->message & resumeFlag) == 1)
        SetThemeCursor(kThemeArrowCursor);
      break;
  }
}

// ****************************************************************************** doMenuChoice

void  doMenuChoice(SInt32 menuChoice)
{
  MenuID        menuID;
  MenuItemIndex menuItem;
       
  menuID = HiWord(menuChoice);
  menuItem = LoWord(menuChoice);

  if(menuID == 0)
    return;

  switch(menuID)
  {
    case mAppleApplication:
      if(menuItem == iAbout)
        SysBeep(10);
      break;
      
    case mFile:
      doFileMenu(menuItem);
      break;
      
    case mWindows:
      doWindowsMenu(menuItem);
      break;    
  }

  HiliteMenu(0);
}

// ******************************************************************************** doFileMenu

void  doFileMenu(MenuItemIndex menuItem)
{
  switch(menuItem)
  {
    case iNew:
      doNewWindow();
      break;

    case iClose:
      doCloseWindow();
      break;      

    case iQuit:
      gDone = true;
      break;
  }
}

// ***************************************************************************** doWindowsMenu

void  doWindowsMenu(MenuItemIndex menuItem)
{
  WindowRef windowRef;

  windowRef = gWindowRefArray[menuItem];
  SelectWindow(windowRef);  
}

// ******************************************************************************* doNewWindow

void  doNewWindow(void)
{
  WindowRef windowRef;
  Str255    untitledString;
  Str255    numberAsString = "\p1";
  Rect      availableBoundsRect, portRect;
  SInt16    windowHeight;
  MenuRef   windowsMenu;

  if(gCurrentNumberOfWindows == kMaxWindows)
  {
    doErrorAlert(eMaxWindows);
    return;
  }

  if(!(windowRef = GetNewCWindow(rNewWindow,NULL,(WindowRef) -1)))
    doErrorAlert(eFailWindow);

  GetIndString(untitledString,rStringList,sUntitled);
  gUntitledWindowNumber += 1;
  if(gUntitledWindowNumber > 1)
  {
    NumToString(gUntitledWindowNumber,numberAsString);
    doConcatPStrings(untitledString,numberAsString);
  }

  SetWTitle(windowRef,untitledString);

  GetAvailableWindowPositioningBounds(GetMainDevice(),&availableBoundsRect);
  GetWindowPortBounds(windowRef,&portRect);
  SetPortWindowPort(windowRef);
  LocalToGlobal(&topLeft(portRect));
  windowHeight = (availableBoundsRect.bottom - portRect.top) - 3;
  if(!gRunningOnX)
    windowHeight -= 27;
  SizeWindow(windowRef,460,windowHeight,false);

  ShowWindow(windowRef);

  if(gUntitledWindowNumber < 10)
  {
    doConcatPStrings(untitledString,"\p/");
    doConcatPStrings(untitledString,numberAsString);
  }
  windowsMenu = GetMenuRef(mWindows);
  InsertMenuItem(windowsMenu,untitledString,CountMenuItems(windowsMenu));    

  SetWRefCon(windowRef,gCurrentNumberOfWindows);

  gCurrentNumberOfWindows ++;
  gWindowRefArray[gCurrentNumberOfWindows] = windowRef;  

  if(gCurrentNumberOfWindows == 1)
  {
    EnableMenuItem(GetMenuRef(mFile),iClose);
    EnableMenuItem(GetMenuRef(mWindows),0);
    DrawMenuBar();
  }
}

// ***************************************************************************** doCloseWindow

void  doCloseWindow(void)
{
  WindowRef windowRef;
  MenuRef   windowsMenu;
  SInt16    a = 1;

  windowRef = FrontWindow();
  DisposeWindow(windowRef);
  gCurrentNumberOfWindows --;

  windowsMenu = GetMenuRef(mWindows);
  while(gWindowRefArray[a] != windowRef)
    a++;
  gWindowRefArray[a] = NULL;
  DeleteMenuItem(windowsMenu,a);

  for(a=1;a<kMaxWindows+1;a++)
  {
    if(gWindowRefArray[a] == NULL)
    {
      gWindowRefArray[a] = gWindowRefArray[a+1];
      gWindowRefArray[a+1] = NULL;
    }
  }  

  if(gCurrentNumberOfWindows == 0)
  {
    DisableMenuItem(GetMenuRef(mFile),iClose);
    DisableMenuItem(GetMenuRef(mWindows),0);
    DrawMenuBar();
  }
}

// ***************************************************************** doInvalidateScrollBarArea

void  doInvalidateScrollBarArea(WindowRef windowRef)
{
  Rect tempRect;

  SetPortWindowPort(windowRef);

  GetWindowPortBounds(windowRef,&tempRect);
  tempRect.left = tempRect.right - kScrollBarWidth;
  InvalWindowRect(windowRef,&tempRect);

  GetWindowPortBounds(windowRef,&tempRect);
  tempRect.top = tempRect.bottom - kScrollBarWidth;
  InvalWindowRect(windowRef,&tempRect);
}

// ************************************************************************** doConcatPStrings

void  doConcatPStrings(Str255 targetString,Str255 appendString)
{
  SInt16 appendLength;

  appendLength = MIN(appendString[0],255 - targetString[0]);

  if(appendLength > 0)
  {
    BlockMoveData(appendString+1,targetString+targetString[0]+1,(SInt32) appendLength);
    targetString[0] += appendLength;
  }
}

// ****************************************************************************** doErrorAlert

void  doErrorAlert(SInt16 errorType)
{
  AlertStdAlertParamRec paramRec;
  ModalFilterUPP        eventFilterUPP;
  Str255                labelText;
  Str255                narrativeText;
  SInt16                itemHit;

  eventFilterUPP = NewModalFilterUPP((ModalFilterProcPtr) eventFilter);

  paramRec.movable       = true;
  paramRec.helpButton    = false;
  paramRec.filterProc    = eventFilterUPP;
  paramRec.defaultText   = (StringPtr) kAlertDefaultOKText;
  paramRec.cancelText    = NULL;
  paramRec.otherText     = NULL;
  paramRec.defaultButton = kAlertStdAlertOKButton;
  paramRec.cancelButton  = 0;
  paramRec.position      = kWindowAlertPositionMainScreen;

  GetIndString(labelText,rStringList,errorType);

  if(errorType == eMaxWindows)
  {
    GetIndString(narrativeText,rStringList,errorType + 1);
    StandardAlert(kAlertCautionAlert,labelText,narrativeText,¶mRec,&itemHit);
    DisposeModalFilterUPP(eventFilterUPP);
  }
  else
  {
    StandardAlert(kAlertStopAlert,labelText,0,¶mRec,&itemHit);
    ExitToShell();
  }  
}

// ******************************************************************************* eventFilter

Boolean  eventFilter(DialogPtr dialogPtr,EventRecord *eventStrucPtr,SInt16 *itemHit)
{
  Boolean handledEvent = false;
  
  if((eventStrucPtr->what == updateEvt) && 
     ((WindowRef) eventStrucPtr->message != GetDialogWindow(dialogPtr)))
  {
    doUpdate(eventStrucPtr);
  }

  return handledEvent;
}

// *******************************************************************************************

Demonstration Program Windows1 Comments

When this program is run, the user should:

o Open and close windows using both the Open and Close commands from the File menu and their
  keyboard equivalents, noting that, whenever a window is opened or closed, a menu item
  representing that window is added to, or deleted from, the Windows menu.

o Note that keyboard equivalents are added to the menu items in the Windows menu for the first
  nine windows opened.

o Activate individual windows by both clicking the content region and pressing the keyboard
  equivalent for the window.

o Send the application to the background and bring it to the foreground, noting window
  activation/deactivation.

o Zoom, close, and resize windows using the zoom box/button, close box/button and size
  box/resize control, noting window updating and activation.

o On Mac OS X, note that, when a window is zoomed to the standard state, the zoom is
  constrained by the current height of the Dock.

o On Mac OS 8/9, choose Show Balloons from the Help menu and move the cursor over the hot
  rectangles in the frontmost window.

If an attempt is made to open more than 10 windows, a movable modal alert appears.

defines

The first nine #defines establish constants representing menu IDs and resources, and window and
menu bar resources.  The next six establish constants representing the resource ID of a 'STR#'
resource and the various strings in that resource.  rPixelPattern represents the resource ID of
the first of ten 'ppat' (pixel pattern) resources.  kMaxWindows controls the maximum number of
windows allowed to be open at one time.

MAX_UINT32 is defined as the maximum possible UInt32 value.  (This will be assigned to
WaitNextEvent's sleep parameter.)  The two fairly common macros which follow are required by,
respectively, the string concatenation function doConcatPStrings and the window creation
function doNewWindow.

Global Variables

The global variable gRunningOnX will be set to true if the program is running on Mac OS X. 
gDone, when set to true, causes the main event loop to be exited and the program to terminate.

gUntitledWindowNumber keeps track of the window numbers to be inserted into the window's title
bar.  This number is incremented each time a new window is opened.  gCurrentNumberOfWindows
keeps track of how many windows are open at any one time.

In this program, CreateStandardWindowMenu is not used to create the Window menu.  The Window
menu is created in the same way as the other menus, and managed ny the program. 
gWindowRefArray[] is central to the matter of maintaining an association between item numbers
in the Window menu and the windows to which they refer, regardless of how many windows are
opened and closed, and in what sequence.  When, for example, a Window menu item is chosen, the
program must be able to locate the window object for the window represented by that menu item
number so as to activate the correct window.

The strategy adopted by this program is to assign the references for each opened window to the
elements of gWindowRefArray[], starting with gWindowRefArray[1] and leaving gWindowRefArray[0]
unused.  If, for example, six windows are opened in sequence, gWindowRefArray[1] to
gWindowRefArray[6] are assigned the references to the window objects for each of those six
windows.  (At the same time, menu items representing each of those windows are progressively
added to the Window menu.)

If, say, the third window opened is then closed, gWindowRefArray[3] is set to NULL and the
window object references in gWindowRefArray[4] to gWindowRefArray[6] are moved down in the
array to occupy gWindowRefArray[3] to gWindowRefArray[5].  Since the Window menu item for the
third window is deleted from the menu when the window is closed, there remains five windows and
their associated menu items, the "compaction" of the array having maintained a direct
relationship between the number of the array element to which each window reference is assigned
and the number of the menu item for that window. 

main

The first action is to call doPreliminaries, which performs certain preliminary actions common
to most applications. 

The next block sets up the menus.  Note that error handling involving the invocation of alerts
is introduced in this program.  If an error occurs, the function doErrorAlert is called to
display either a stop or caution movable modal alert advising of the nature of the error.

In the final three lines, gWindowRefArray[] is initialised  and the main event loop is entered.

doPreliminaries

Note that MoreMasterPointers is called with 224 passed in the inCount parameter to provide
sufficient master pointers for this program.

eventLoop

eventLoop will exit when gDone is set to true, which occurs when the user selects Quit from the
File menu.  (As an aside, note that the sleep parameter in the WaitNextEvent call is set to
MAX_UINT32, which is defined as the maximum possible UInt32 value.)

doEvents

doEvents switches according to the event type received.

mouseDown, updateEvt, activateEvt and osEvt events are of significance to the windows aspects
of this demonstration.  keyDown events are significant only with regard to File and Window menu
keyboard equivalents.

doMouseDown

doMouseDown continues the processing of mouseDown events, switching according to the part code.

The inContent case results in a call to SelectWindow if the window in which the mouse-down
occurred is not the front window.  SelectWindow:

o Unhighlights the currently active window, brings the specified window to the front and
  highlights it.

o Generates activate events for the two windows.

o Moves the previously active window to a position immediately behind the specified window.

The inDrag case results in a call to DragWindow, which retains control until the user releases
the mouse button.  The third parameter in the DragWindow call establishes the limits, in global
screen coordinates, within which the user is allowed to drag the window.  In Carbon, NULL may
be passed in this parameter.  This has the effect of setting the third parameter to the
bounding rectangle of the desktop region (also known as the "gray region").

The inGoAway case results in a call to TrackGoAway, which retains control until the user
releases the mouse button.  If the pointer is still within the close box/button when the mouse
button is released, the function doCloseWindow is called.

At the inGrow case, the first three lines establish the resizing constraints.  The top and left
fields of the Rect variable constraintRect are assigned values representing the minimum height
and width to which the window may be resized.  The bottom and right fields, which establish the
maximum height and width, are assigned the maximum possible SInt16 value.  (Since the mouse
cursor cannot be moved beyond the edges of the screen (or screens in a multi-monitor system),
these values mean that the window can be resized larger to the limits of mouse cursor
movement.)

ResizeWindow retains control until the user releases the mouse button.  When the mouse button
is released, ResizeWindow redraws the window frame (that is, all but the content region) in the
new size and, where window height and/or width has been increased, adds the newly-exposed areas
of the content region to update region (on Mac OS 8/9).  (Note that, in Carbon, the fourth
(newContentRect) parameter may be set to NULL if the new dimension of the window's content
region is not required.)

The call to ResizeWindow is bracketed by two calls to the function doInvalidateScrollBarArea. 
In this program, scroll bars are not used but it has been decided to, firstly, limit update
drawing to the window's content region less the areas normally occupied by scroll bars and,
secondly, to use DrawGrowIcon to draw the draw scroll bar delimiting lines.  (For Mac OS 8/9,
this is the usual practice for windows with a size box but no scroll bars.  The DrawGrowIcon
call is ignored on Mac OS X.)

The first call to doInvalidateScrollBarArea is necessary to cater for the case where the window
is resized larger.  If this call is not made, the scroll bar areas prior to the resize will not
be redrawn by the window updating function unless these areas are programmatically added to the
new update region created by the Window Manager as a result of the resizing action.

The second call to doInvalidateScrollBarArea is necessary to cater for the case where the
window is resized smaller.  This call works in conjunction with the EraseRgn call in the
function doUpdateWindow.  The call to doInvalidateScrollBarArea results in an update event
being generated, and the call to EraseRgn in the doUpdateWindow function causes the update
region (that is, in this case, the scroll bar areas) to be erased.  (Remember that, on Mac OS
8/9, between the calls to BeginUpdate and EndUpdate, the visible region equates to the update
region and that QuickDraw limits its drawing to the update region.)

At the inZoomIn/inZoomOut case, the first action is to assign the desired height and width of
the windows's standard state content region to the fields of a Point variable.  This variable
is then passed in the second parameter of a call to IsWindowInStandardState, which sets the
variable zoomPart to either true or false depending on whether the window is currently in the
standard state or the user state.  TrackBox is then called, taking control until the user
releases the mouse button.  If the mouse button is released while the pointer is still within
the zoom box, ZoomWindowIdeal is called to zoom the window in accordance with human interface
guidelines.  The second parameter tells ZoomWindow whether to zoom out to the standard state or
in to the user state.

doUpdate

On Mac OS 8/9 and Mac OS X, an update event will be received:

o When the window is created.

o When the window is resized larger.

o When the window is resized smaller (because of calls to InvalWindowRect in the function
  doInvalidateScrollBarArea).

o When the window is zoomed.

On Mac OS 8/9, update events will also be received when a window has a non-empty update region.

doUpdate attends to basic window updating.  On Mac OS 8/9, the call to BeginUpdate clips the
visible region to the intersection of the visible region and the update region.  The visible
region is now a sort of proxy for the update region.  The graphics port is then set before the
function doUpdateWindow is called to redraw the content region.  On Mac OS 8/9, the EndUpdate
call restores the window's true visible region.  (The calls to BeginUpdate and EndUpdate are
ignored on Mac OS X.)

doUpdateWindow

doUpdateWindow is concerned with redrawing the window's contents less the scroll bar areas.

The first action is to retrieve the window object reference from the message field of the event
structure.

The next block retrieves the handle to the window's visible region, following which EraseRgn is
called for reasons explained at doMouseDown, above.

The window's graphics port's bounding rectangle is then retrieved, following which the right
and bottom fields are adjusted to exclude the scroll bar areas.  The next four lines fill this
rectangle with a plain colour pattern provided by a 'ppat' resource, simply as a means of
proving the correctness of the window updating process.

Note the call to GetWRefCon, which retrieves the window's reference constant stored in the
window object.  As will be seen, whenever a new window is opened, a value between 1 and
kMaxWindows is stored as a reference constant in the window object.  In this function, this is
just a convenient number to be added to the base resource ID (128) in the single parameter of
the GetPixPat call, ensuring that FillCRect has a different pixel pattern to draw in each
window.

The call to DrawGrowIcon draws the scroll bar delimiting lines (on Mac OS 8/9).  Note that this
call, the preceding EraseRgn call, and the calls to doInvalidateScrollbarArea are made for
"cosmetic" purposes only and would not be required if the window contained scroll bars.

If the program is running on Mac OS 8/9, the remaining lines draw two rectangles and some text
in the windows to visually represent to the user the otherwise invisible "hot rectangles"
defined in the 'hrct' resource and associated with the window by the 'hwin' resource.  When
Show Balloons is chosen from the Help menu, the help balloons will be invoked when the cursor
moves over these rectangles.

doActivate

doActivate attends to those aspects of window activation not handled by the Window Manager.

The modifiers field of the event structure is tested to determine whether the window in
question is being activated or deactivated.  The result of this test is passed as a parameter
in the call to the function doActivateWindow.

doActivateWindow

In this demonstration, the remaining actions carried out in response to an activateEvt are
limited to placing/removing checkmarks in/from items in the Window menu.

The first step is to associate the received WindowRef with its item number in the Window menu. 
At the while loop, the array maintained for that purpose is searched until a match is found. 
The array element number at which the match is found correlates directly with the menu item
number; accordingly, this is assigned to the variable menuItem, which is used in the following
CheckMenuItem calls.  Whether the checkmark is added or removed depends on whether the window
in question is being activated or deactivated, a condition passed to the call to
doActivateWindow as its second parameter.

The call to DrawGrowIcon ensures that the scroll bar area delimiting lines will be drawn in
gray when the window is deactivated (on Mac OS 8/9).

doOSEvent

doOSEvent handles operating system events.  In this demonstration, action is taken only in the
case of resume events.  If the event is a resume event, the cursor is set to the arrow shape.

doMenuChoice and doFileMenu

doMenuChoice switches according to the menu choices of the user.  doFileMenu switches according
to the File menu item choice of the user.

doWindowsMenu

doWindowsMenu takes the item number of the selected Window menu item and, since this equates to
the number of the array element in which the associated window object reference is stored,
extracts the window object reference associated with the menu item.  This is used in the call
to SelectWindow, which generates the activateEvts required to activate and deactivate the
appropriate windows.

doNewWindow

doNewWindow opens a new window and attends to associated tasks.

In the first block, if the current number of open windows equals the maximum allowable
specified by kMaxWindows, a caution movable modal alert is called up via the function
doErrorAlert (with the string represented by eMaxWindows displayed) and an immediate return is
executed when the user clicks the alert's OK button.

At the next block, the new window is created by the call to GetNewCWindow.  The third parameter
specifies that the window is to be opened in front of all other windows.  If the call is not
successful for any reason, a stop movable modal alert is called up via the function
doErrorAlert (with the string represented by eFailWindow displayed) and the program terminates
when the user clicks the alert's OK button.

The next seven lines create the string which will be used to set the window's title.  The code
reflects the fact that Aqua Human Interface Guidelines require that a number only be appended
to "untitled" for the second and later windows.  Accordingly, concatenating a number to the
string "untitled" is not effected for the first window created.

GetIndString retrieves the string "untitled " from the specified 'STR#' resource and the global
variable which keeps track of the numbers for the title bar is incremented.  If this is not the
first window to be created, NumToString converts that number to a Pascal string and this string
is concatenated to the "untitled " string.  The SetWTitle call then sets the window's title.

The next block sets adjusts the size of the window before it is displayed.  The width is set to
460 pixels and the height is adjusted according to the available screen real estate.

The call to GetAvailableWindowPositioningBounds returns, in global coordinates, the available
real estate on the main screen (device).  This excludes the menu bar and, on Mac OS X, the
Dock.  The call to SetPortWindowPort sets the window's graphics port as the current port, a
necessary precursor to the call to LocalToGlobal, which converts the top-left (local)
coordinates of the port rectangle to global coordinates.  The height of the rectangle returned
by GetAvailableWindowPositioningBounds is then reduced by the distance of the top of the port
rectangle from the top of the screen, and then further reduced by three.  On Mac OS X, this
will cause the bottom of the window to be just above the top of the Dock.  If the program is
running on Mac OS 8/9, the height is reduced by a further 27 pixels to accommodate the height
of the control strip.  The call to SizeWindow sets the window's size.  (The window's location
is determined by the positioning specification in the window's 'WIND' resource.)

The ShowWindow call makes the window visible.

The next block adds the metacharacter \ and the window number to the string used to set the
window title (thus setting up the Command key equivalent) before InsertMenuItem is called to
create a new menu item to the Window menu.  Note that the Command-key equivalent is only added
for the first nine windows opened.)

The SetWRefCon call stores the value represented by gCurrentNumberOfWindows in the window
object as the window's reference constant.  As previously stated, in this demonstration this is
used to select a pixel pattern to draw in each window's content region.

At the next two lines, the variable which keeps track of the current number of opened windows
is incremented and the appropriate element of the window reference array is assigned the
reference to newly opened window's window object.

The last block enables the Window menu and the Close item in the File menu when the first
window is opened.

doCloseWindow

The function doCloseWindow closes an open window and attends to associated tasks.

At the first two lines, a reference to the frontmost window's window object is retrieved and
passed in the call to DisposeWindow.  DisposeWindow removes the window from the screen, removes
it from the window list, and discards all its data storage.  With the window closed, the global
variable that keeps track of the number of windows currently open is decremented.

The next block deletes the associated menu item from the Window menu.  At the first four lines,
the array element in which the window object reference in question is located is searched out,
the element number (which correlates directly with the menu item number) is noted and the
element is set to NULL.  The call to DeleteMenuItem then deletes the menu item.

The for loop "compacts" the array, that is, it moves the contents of all elements above the
NULLed element down by one, maintaining the correlation with the Windows menu.

The last block disables the Windows menu and the Close item in the File menu if no windows
remain open as a result of this closure.

doInvalidateScrollBarArea

doInvalidateScrollBarArea invalidates that part of the window's content area which would
ordinarily be occupied by scroll bars.  The function simply retrieves the coordinates of the
content area into a local Rect and reduces this Rect to the relevant scroll bar area before
invalidating that area, that is, adding it to the window's update region.

doConcatPStrings

The function doConcatPStrings concatenates two Pascal strings.

doErrorAlert and eventFilter

doErrorAlert displays either a caution alert or a stop alert with a specified string (two
strings in the case of the eMaxWindows error) extracted from the 'STR#' resource identified by
rStringList.  eventFilter supports doErrorAlert.

The creation of alerts using the StandardAlert function, and event filter functions, are
addressed at Chapter 8.
 
AAPL
$117.60
Apple Inc.
-1.03
MSFT
$47.47
Microsoft Corpora
-0.12
GOOG
$541.08
Google Inc.
+1.81

MacTech Search:
Community Search:

Software Updates via MacUpdate

MacUpdate Desktop 6.0.3 - Discover and i...
MacUpdate Desktop 6 brings seamless 1-click installs and version updates to your Mac. With a free MacUpdate account and MacUpdate Desktop 6, Mac users can now install almost any Mac app on macupdate.... Read more
SteerMouse 4.2.2 - Powerful third-party...
SteerMouse is an advanced driver for USB and Bluetooth mice. It also supports Apple Mighty Mouse very well. SteerMouse can assign various functions to buttons that Apple's software does not allow,... Read more
iMazing 1.1 - Complete iOS device manage...
iMazing (was DiskAid) is the ultimate iOS device manager with capabilities far beyond what iTunes offers. With iMazing and your iOS device (iPhone, iPad, or iPod), you can: Copy music to and from... Read more
PopChar X 7.0 - Floating window shows av...
PopChar X helps you get the most out of your font collection. With its crystal-clear interface, PopChar X provides a frustration-free way to access any font's special characters. Expanded... Read more
Carbon Copy Cloner 4.0.3 - Easy-to-use b...
Carbon Copy Cloner backups are better than ordinary backups. Suppose the unthinkable happens while you're under deadline to finish a project: your Mac is unresponsive and all you hear is an ominous,... Read more
ForeverSave 2.1.3 - Universal auto-save...
ForeverSave auto-saves all documents you're working on while simultaneously doing backup versioning in the background. Lost data can be quickly restored at any time. Losing data, caused by... Read more
Voila 3.8.1 - Capture, annotate, organiz...
Voila is a screen-capture, recording, and annotation tool that is a full-featured replacement for Mac's screen-capture and screen-recording capabilities. It has a large and robust set of editing,... Read more
SyncTwoFolders 2.0.6 - Syncs two user-sp...
SyncTwoFolders simply synchronizes two folders. It supports synchronization across mounted network drives and it is a possibility to run a simulation showing in a log what will be done. Please visit... Read more
Duplicate Annihilator 5.1.1 - Find and d...
Duplicate Annihilator takes on the time-consuming task of comparing the images in your iPhoto library using effective algorithms to make sure that no duplicate escapes. Duplicate Annihilator detects... Read more
HandBrake 0.10.0 - Versatile video encod...
HandBrake is a tool for converting video from nearly any format to a selection of modern, widely supported codecs. Supported Sources: VIDEO_TS folder, DVD image or real DVD (unencrypted -- CSS is... Read more

Latest Forum Discussions

See All

Screeny (Utilities)
Screeny 1.0 Device: iOS iPhone Category: Utilities Price: $.99, Version: 1.0 (iTunes) Description: Screeny is an utility app that helps you save space consumed by screenshots. It screens your camera roll and helps you to filter and... | Read more »
Tilt to Live Bundle Set to Arrive This T...
Tilt to Live Bundle Set to Arrive This Thanksgiving Posted by Ellis Spice on November 25th, 2014 [ permalink ] One Man Left has unveiled an upcoming Tilt to Live bundle, allowing players to get the series for a di | Read more »
BattleLore: Command (Entertainment)
BattleLore: Command 1.0 Device: iOS Universal Category: Entertainment Price: $9.99, Version: 1.0 (iTunes) Description: ***NOTE: Compatible with iPad 2/iPad mini, iPod touch 5 and up and iPhone 4S and up – WILL NOT RUN ON EARLIER... | Read more »
Weather Or Not Review
Weather Or Not Review By Jennifer Allen on November 25th, 2014 Our Rating: :: STYLISH WEATHER REPORTINGiPhone App - Designed for the iPhone, compatible with the iPad Check the weather quickly and conveniently with Weather or Not... | Read more »
The All-New Football Manager Handheld 20...
The All-New Football Manager Handheld 2015 is Available Now Posted by Jessica Fisher on November 25th, 2014 [ permalink ] Universal App - Designed for iPhone and iPad | Read more »
Six iOS Games to Get You Ready for Thank...
Image Source: Friends Wiki At this point in the month, you or at least a few people you know are probably getting ready to scramble around (or are already scrambling around) for Thanksgiving Dinner. It’s a hectic day of precise oven utilization, but... | Read more »
Call of Duty: Heroes: Tips, Tricks, and...
Hello Heroes: What’d we think of Call of Duty‘s take on Clash of Clans? Check out our Call of Duty: Heroes review to find out! Just downloaded Call of Duty: Heroes and need some handy tips and tricks on how to get ahead of the rest? As we often do,... | Read more »
Call of Duty: Heroes Review
Call of Duty: Heroes Review By Jennifer Allen on November 25th, 2014 Our Rating: :: CLASH OF FRANCHISESUniversal App - Designed for iPhone and iPad Mix Clash of Clans with Call of Duty, and this is what you get.   | Read more »
Slider Review
Slider Review By Jordan Minor on November 25th, 2014 Our Rating: :: SLIDE TO PLAYUniversal App - Designed for iPhone and iPad Slider has all the excitement of unlocking your phone screen.   | Read more »
oh my giraffe (Games)
oh my giraffe 1.0.0 Device: iOS Universal Category: Games Price: $1.99, Version: 1.0.0 (iTunes) Description: Eat fruits while being chased by lions. Cut the vines to send fruit plummeting onto the lions. Don't worry, your flexible... | Read more »

Price Scanner via MacPrices.net

Early Black Friday MacBook Pro sale: 15-inch...
 Best Buy has posted early Black Friday prices on 15″ Retina MacBook Pros, with models on sale for $300 off MSRP on their online store for a limited time. Choose free local store pickup (if available... Read more
A9 Chips Already?
It’s barely more than a couple of months since Apple got the first A8 systems-on-chip into consumer hands, but rumor and news focus is already turning to the next-generation A9 SoC. Apple Daily... Read more
NewerTech Announces NuGuard KXs Impact X-Orbi...
NewerTech has announced updates to its family of Impact X-Orbing Screen Armor bringing military grade, triple layer protection to Apple’s new iPhone 6 and 6 Plus. Like all models in the NuGuard KXs... Read more
13-inch 1.4GHz MacBook Air on sale for $889,...
 B&H Photo has the 13″ 1.4GHz/128GB MacBook Air on sale for $889 including free shipping plus NY tax only. Their price is $110 off MSRP. B&H will also include free copies of Parallels Desktop... Read more
Save up to $300 on Macs and iPads with your A...
Purchase a new Mac or iPad at The Apple Store for Education and take up to $300 off MSRP. All teachers, students, and staff of any educational institution qualify for the discount. Shipping is free,... Read more
Apple refurbished Mac Pros available for up t...
The Apple Store is offering Apple Certified Refurbished Mac Pros for up to $600 off the cost of new models. An Apple one-year warranty is included with each Mac Pro, and shipping is free. The... Read more
Jumptuit Launches One-Tap Windows 8.1 iTunes...
Jumptuit has launched Windows 8.1 support for One-Tap iTunes Sync. with which Windows 8.1 users can now easily sync their iTunes libraries with Microsoft OneDrive. Jumptuit provides easy access from... Read more
Apple restocks refurbished 13-inch 2014 Retin...
The Apple Store has restocked Apple Certified Refurbished 2014 13″ 2.6GHz Retina MacBook Pros for up to $230 off the cost of new models. An Apple one-year warranty is included with each model, and... Read more
CEA Study Finds More People Recycling Electro...
A new study by the Consumer Electronics Association (CEA) finds that electronics recycling receives the continued and growing support of consumers. According to the CEA,s Recycling and Reuse Study,... Read more
15″ 2.2GHz Retina MacBook Pro on sale for $17...
 B&H Photo has the 2014 15″ 2.2GHz Retina MacBook Pro on sale today for $1749. Shipping is free, and B&H charges NY sales tax only. B&H will also include free copies of Parallels Desktop... Read more

Jobs Board

*Apple* Solutions Consultant (ASC) - Apple (...
**Job Summary** The ASC is an Apple employee who serves as an Apple brand ambassador and influencer in a Reseller's store. The ASC's role is to grow Apple Read more
Senior Event Manager, *Apple* Retail Market...
…This senior level position is responsible for leading and imagining the Apple Retail Team's global event strategy. Delivering an overarching brand story; in-store, Read more
*Apple* Retail - Multiple Positions (US) - A...
Sales Specialist - Retail Customer Service and Sales Transform Apple Store visitors into loyal Apple customers. When customers enter the store, you're also the Read more
*Apple* Solutions Consultant (ASC) - Apple (...
**Job Summary** The ASC is an Apple employee who serves as an Apple brand ambassador and influencer in a Reseller's store. The ASC's role is to grow Apple Read more
*Apple* Solutions Consultant (ASC) - Apple (...
**Job Summary** The ASC is an Apple employee who serves as an Apple brand ambassador and influencer in a Reseller's store. The ASC's role is to grow Apple Read more
All contents are Copyright 1984-2011 by Xplain Corporation. All rights reserved. Theme designed by Icreon.