TweetFollow Us on Twitter

MACINTOSH C CARBON

Demonstration Program Miscellany

Goto Contents

// *******************************************************************************************
// Miscellany.h                                                             CARBON EVENT MODEL
// *******************************************************************************************
// 
// This program demonstrates:
//
// o  The use of the Notification Manager to allow an application running in the background to
//    to communicate with the foreground application.
//
// o  The use of the determinate progress bar control to show progress during a time-
//    consuming operation, together with scanning the event queue for Command-period key-down
//    events for the purpose of terminating the lengthy operation  before it concludes of its
//    own accord.
//
// o  The use of the Color Picker to solicit a choice of colour from the user.
//
// o  Image drawing optimisation in a multi-monitors environment. 
//
// o  Help tags for controls and windows with minimum and maximum content. 
//
// The program utilises the following resources:
//
// o  A 'plst' resource.
//
// o  An 'MBAR' resource, and 'MENU' resources for Apple, File, Edit and Demonstration menus
//    (preload, non-purgeable).
//
// o  A 'DLOG' resource (purgeable), and associated 'DITL', 'dlgx', and 'dftb' resources
//    (purgeable), for a dialog box in which the progress indicator is displayed.
//
// o  'CNTL' resources (purgeable) for the progress indicator dialog.
//
// o  'icn#', 'ics4', and 'ics8' resources (non-purgeable) which contain the application icon
//    shown in the Application menu during the Notification Manager demonstration.
//
// o  A 'snd ' resource (non-purgeable) used in the Notification Manager demonstration.
//
// o  A 'STR ' resource (non-purgeable) containing the text displayed in the alert box invoked
//    by the Notification Manager.
//
// o  'STR#' resources (purgeable) containing the label and narrative strings for the
//    notification-related alert displayed by Miscellany and the minimum and maximum Help tag
//    content.
//
// 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  iQuit              12
#define mDemonstration      131
#define  iNotification      1
#define  iProgress          2
#define  iColourPicker      3
#define  iMultiMonitors     4
#define  iHelpTag           5
#define rWindow             128
#define rDialog             128
#define  iProgressIndicator 1
#define rIconFamily         128
#define rBarkSound          8192
#define rString             128
#define rAlertStrings       128
#define  indexLabel         1
#define  indexNarrative     2
#define rPicture            128
#define topLeft(r)          (((Point *) &(r))[0])
#define botRight(r)         (((Point *) &(r))[1])

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

void      main                           (void);
void      doPreliminaries                (void);
OSStatus  appEventHandler                (EventHandlerCallRef,EventRef,void *);
OSStatus  windowEventHandler             (EventHandlerCallRef,EventRef,void *);
void      doMenuChoice                   (MenuID,MenuItemIndex);

void      doSetUpNotification            (void);
void      doPrepareNotificationStructure (void);
void      doIdle                         (void);
void      doDisplayMessageToUser         (void);

void      doProgressBar                  (void);

void      deviceLoopDraw                 (SInt16,SInt16,GDHandle,SInt32);

void      doColourPicker                 (void);
void      doDrawColourPickerChoice       (void);
char      *doDecimalToHexadecimal        (UInt16 n);

void      doHelpTagControl               (void);
void      doHelpTagWindow                (void);

// *******************************************************************************************
// Miscellany.c
// *******************************************************************************************

#include "Miscellany.h"

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

DeviceLoopDrawingUPP gDeviceLoopDrawUPP;
WindowRef            gWindowRef;
ControlRef           gBevelButtonControlRef;
ProcessSerialNumber  gProcessSerNum;
Boolean              gMultiMonitorsDrawDemo = false;
Boolean              gColourPickerDemo  = false;
Boolean              gHelpTagsDemo = false;
RGBColor             gWhiteColour = { 0xFFFF, 0xFFFF, 0xFFFF };
RGBColor             gBlueColour  = { 0x6666, 0x6666, 0x9999 };

extern Boolean       gNotificationInQueue;

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

void  main(void)
{
  MenuBarHandle menubarHdl;
  SInt32        response;
  MenuRef       menuRef;
  Rect          contentRect = { 100,100,402,545 };
  Rect          portRect;
  Rect          controlRect = { 65,10,155,100 };
  EventTypeSpec applicationEvents[] = { { kEventClassApplication, kEventAppActivated    },
                                        { kEventClassCommand,     kEventProcessCommand  } };
  EventTypeSpec windowEvents[]      = { { kEventClassWindow, kEventWindowDrawContent    },
                                        { kEventClassWindow, kEventWindowGetIdealSize   },
                                        { kEventClassWindow, kEventWindowGetMinimumSize },
                                        { kEventClassWindow, kEventWindowBoundsChanged  } };

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

  doPreliminaries();

  // ...................................................... create universal procedure pointer

  gDeviceLoopDrawUPP = NewDeviceLoopDrawingUPP((DeviceLoopDrawingProcPtr) deviceLoopDraw);

  // ............................................................... set up menu bar and menus

  menubarHdl = GetNewMBar(rMenubar);
  if(menubarHdl == NULL)
    ExitToShell();
  SetMenuBar(menubarHdl);
  DrawMenuBar();

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

  // ............................................. install application event handler and timer

  InstallApplicationEventHandler(NewEventHandlerUPP((EventHandlerProcPtr) appEventHandler),
                                 GetEventTypeCount(applicationEvents),applicationEvents,
                                 0,NULL);

  InstallEventLoopTimer(GetCurrentEventLoop(),0,1,
                        NewEventLoopTimerUPP((EventLoopTimerProcPtr) doIdle),NULL,NULL);

  // ............................................................................. open window

  CreateNewWindow(kDocumentWindowClass,kWindowStandardHandlerAttribute |
                  kWindowStandardDocumentAttributes,&contentRect,&gWindowRef);

  ChangeWindowAttributes(gWindowRef,0,kWindowCloseBoxAttribute);
  SetWTitle(gWindowRef,"\pMiscellany");
  RepositionWindow(gWindowRef,NULL,kWindowAlertPositionOnMainScreen);

  SetPortWindowPort(gWindowRef);
  TextSize(10);

  ShowWindow(gWindowRef);
  GetWindowPortBounds(gWindowRef,&portRect);
  InvalWindowRect(gWindowRef,&portRect);

  // ............................................................ install window event handler

  InstallWindowEventHandler(gWindowRef,
                            NewEventHandlerUPP((EventHandlerProcPtr) windowEventHandler),
                            GetEventTypeCount(windowEvents),windowEvents,0,NULL);

  // ............................................................ create control and help tags

  CreateBevelButtonControl(gWindowRef,&controlRect,CFSTR("Control"),
                           kControlBevelButtonNormalBevel,kControlBehaviorPushbutton,
                           NULL,0,0,0,&gBevelButtonControlRef);
  doHelpTagControl();
  HideControl(gBevelButtonControlRef);
  doHelpTagWindow();
  HMSetHelpTagsDisplayed(false);

  // ............................................... get process serial number of this process

  GetCurrentProcess(&gProcessSerNum);  

  // .............................................................. run application event loop

  RunApplicationEventLoop();
}

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

void  doPreliminaries(void)
{
  MoreMasterPointers(640);
  InitCursor();
}

// *************************************************************************** appEventHandler

OSStatus  appEventHandler(EventHandlerCallRef eventHandlerCallRef,EventRef eventRef,
                          void * userData)
{
  OSStatus      result = eventNotHandledErr;
  UInt32        eventClass;
  UInt32        eventKind;
  HICommand     hiCommand;
  MenuID        menuID;
  MenuItemIndex menuItem;

  eventClass = GetEventClass(eventRef);
  eventKind  = GetEventKind(eventRef);

  switch(eventClass)
  {
    case kEventClassApplication:
      if(eventKind == kEventAppActivated)
      {
        if(gNotificationInQueue)
          doDisplayMessageToUser();
        result = noErr;
      }
      break;

    case kEventClassCommand:
      if(eventKind == kEventProcessCommand)
      {
        GetEventParameter(eventRef,kEventParamDirectObject,typeHICommand,NULL,
                          sizeof(HICommand),NULL,&hiCommand);
        menuID = GetMenuID(hiCommand.menu.menuRef);
        menuItem = hiCommand.menu.menuItemIndex;
        if((hiCommand.commandID != kHICommandQuit) && 
           (menuID >= mAppleApplication && menuID <= mDemonstration))
        {
          doMenuChoice(menuID,menuItem);
          result = noErr;
        }
      }
      break;
  }

  return result;
}

// ************************************************************************ windowEventHandler

OSStatus  windowEventHandler(EventHandlerCallRef eventHandlerCallRef,EventRef eventRef,
                             void* userData)
{
  OSStatus  result = eventNotHandledErr;
  UInt32    eventClass;
  UInt32    eventKind;
  WindowRef windowRef;
  SInt32    deviceLoopUserData;
  RgnHandle regionHdl;
  Rect      portRect, positioningBounds;
  Point     idealHeightAndWidth, minimumHeightAndWidth;

  eventClass = GetEventClass(eventRef);
  eventKind  = GetEventKind(eventRef);

  switch(eventClass)
  {
    case kEventClassWindow:
      GetEventParameter(eventRef,kEventParamDirectObject,typeWindowRef,NULL,sizeof(windowRef),
                        NULL,&windowRef);
      switch(eventKind)
      {
        case kEventWindowDrawContent:
          if(gMultiMonitorsDrawDemo)
          {
            RGBBackColor(&gWhiteColour);
            deviceLoopUserData = (SInt32) windowRef;
            regionHdl = NewRgn();
            if(regionHdl)
            {
              GetPortVisibleRegion(GetWindowPort(windowRef),regionHdl);
              DeviceLoop(regionHdl,gDeviceLoopDrawUPP,deviceLoopUserData,0);
              DisposeRgn(regionHdl);
            }
          }
          else if(gColourPickerDemo )
          {
            RGBBackColor(&gBlueColour);
            GetWindowPortBounds(windowRef,&portRect);
            EraseRect(&portRect);
            doDrawColourPickerChoice();
          }
          else
          {
            RGBBackColor(&gBlueColour);
            GetWindowPortBounds(windowRef,&portRect);
            EraseRect(&portRect);
            if(gHelpTagsDemo)
            {
              Draw1Control(gBevelButtonControlRef);
              RGBForeColor(&gWhiteColour);
              MoveTo(10,20);
              DrawString("\pHover the cursor in the window, and over the bevel button, ");
              DrawString("\puntil the Help tag appears.");
              MoveTo(10,35);
              DrawString("\pPress the Command key to invoke the maximum content.");
              MoveTo(10,50);
              DrawString("\pDrag the window to a new location.");
            }
          }
          result = noErr;
          break;

        case kEventWindowGetIdealSize:
          GetAvailableWindowPositioningBounds(GetMainDevice(),&positioningBounds);
          idealHeightAndWidth.v = positioningBounds.bottom;
          idealHeightAndWidth.h = positioningBounds.right;
          SetEventParameter(eventRef,kEventParamDimensions,typeQDPoint,
                            sizeof(idealHeightAndWidth),&idealHeightAndWidth);
           result = noErr;
          break;

        case kEventWindowGetMinimumSize:
          minimumHeightAndWidth.v = 302; 
          minimumHeightAndWidth.h = 445;
          SetEventParameter(eventRef,kEventParamDimensions,typeQDPoint,
                            sizeof(minimumHeightAndWidth),&minimumHeightAndWidth);
          result = noErr;
          break;

        case kEventWindowBoundsChanged:
          doHelpTagWindow();
          GetWindowPortBounds(windowRef,&portRect);
          InvalWindowRect(windowRef,&portRect);
          result = noErr;
          break;
      }
      break;
  }

  return result;
}

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

void  doMenuChoice(MenuID menuID,MenuItemIndex menuItem)
{
  Rect portRect;

  if(menuID == 0)
    return;

  switch(menuID)
  {
    case mAppleApplication:
      if(menuItem == iAbout)
        SysBeep(10);
      break;

    case mDemonstration:
      gMultiMonitorsDrawDemo = gColourPickerDemo = gHelpTagsDemo = false;
      if(HMAreHelpTagsDisplayed)
        HMSetHelpTagsDisplayed(false);
      HideControl(gBevelButtonControlRef);
      GetWindowPortBounds(gWindowRef,&portRect);

      switch(menuItem)
      {
        case iNotification:
          RGBBackColor(&gBlueColour);
          EraseRect(&portRect);
          doSetUpNotification();
          break;
          
        case iProgress:
          RGBBackColor(&gBlueColour);
          EraseRect(&portRect);
          doProgressBar();
          break;

        case iColourPicker:
          gColourPickerDemo = true;
          doColourPicker();
          break;
          
        case iMultiMonitors:
          gMultiMonitorsDrawDemo = true;
          InvalWindowRect(gWindowRef,&portRect);
          break;

        case iHelpTag:
          gHelpTagsDemo = true;
          InvalWindowRect(gWindowRef,&portRect);
          ShowControl(gBevelButtonControlRef);
          HMSetHelpTagsDisplayed(true);
          break;
      }

      break;
  }
}

// *******************************************************************************************
// Notification.c
// *******************************************************************************************

#include "Miscellany.h"

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

NMRec                      gNotificationStructure;
long                       gStartingTickCount;
Boolean                    gNotificationDemoInvoked;
Boolean                    gNotificationInQueue;
extern WindowRef           gWindowRef;
extern ProcessSerialNumber gProcessSerNum;
extern RGBColor            gWhiteColour;
extern RGBColor            gBlueColour;

// *********************************************************************** doSetUpNotification

void  doSetUpNotification(void)
{
  doPrepareNotificationStructure();
  gNotificationDemoInvoked = true;

  gStartingTickCount = TickCount();

  RGBForeColor(&gWhiteColour);
  MoveTo(10,279);
  DrawString("\pPlease click on the desktop now to make the Finder ");
  DrawString("\pthe frontmost application.");
  MoveTo(10,292);
  DrawString("\p(This application will post a notification 10 seconds from now.)");
}

// ************************************************************ doPrepareNotificationStructure

void  doPrepareNotificationStructure(void)
{
  Handle       iconSuiteHdl;
  Handle       soundHdl;
  StringHandle stringHdl;

  GetIconSuite(&iconSuiteHdl,rIconFamily,kSelectorAllSmallData);
  soundHdl = GetResource('snd ',rBarkSound);
  stringHdl = GetString(rString);

  gNotificationStructure.qType    = nmType;
  gNotificationStructure.nmMark   = 1;
  gNotificationStructure.nmIcon   = iconSuiteHdl;
  gNotificationStructure.nmSound  = soundHdl;
  gNotificationStructure.nmStr    = *stringHdl;
  gNotificationStructure.nmResp   = NULL;
  gNotificationStructure.nmRefCon = 0;
}

// ************************************************************************************ doIdle

void  doIdle(void)
{
  ProcessSerialNumber frontProcessSerNum;
  Boolean             isSameProcess;
  Rect                portRect;

  if(gNotificationDemoInvoked)
  {
    if(TickCount() > gStartingTickCount + 600)
    {
      GetFrontProcess(&frontProcessSerNum);
      SameProcess(&frontProcessSerNum,&gProcessSerNum,&isSameProcess);
  
      if(!isSameProcess)
      {
        NMInstall(&gNotificationStructure);
        gNotificationDemoInvoked = false;
        gNotificationInQueue = true;
      }
      else
      {
        doDisplayMessageToUser();
        gNotificationDemoInvoked = false;
      }

      GetWindowPortBounds(gWindowRef,&portRect);
      EraseRect(&portRect);
    }
  }
}

// ******************************************************************** doDisplayMessageToUser

void  doDisplayMessageToUser(void)
{
  Rect                  portRect;
  AlertStdAlertParamRec paramRec;
  Str255                labelText;
  Str255                narrativeText;
  SInt16                itemHit;

  if(gNotificationInQueue)
  {
    NMRemove(&gNotificationStructure);
    gNotificationInQueue = false;
  }

  GetWindowPortBounds(gWindowRef,&portRect);
  EraseRect(&portRect);
  
  paramRec.movable       = true;
  paramRec.helpButton    = false;
  paramRec.filterProc    = NULL;
  paramRec.defaultText   = (StringPtr) kAlertDefaultOKText;
  paramRec.cancelText    = NULL;
  paramRec.otherText     = NULL;
  paramRec.defaultButton = kAlertStdAlertOKButton;
  paramRec.cancelButton  = 0;
  paramRec.position      = kWindowDefaultPosition;

  GetIndString(labelText,rAlertStrings,indexLabel);
  GetIndString(narrativeText,rAlertStrings,indexNarrative);

  StandardAlert(kAlertNoteAlert,labelText,narrativeText,¶mRec,&itemHit);

  DisposeIconSuite(gNotificationStructure.nmIcon,false);
  ReleaseResource(gNotificationStructure.nmSound);
  ReleaseResource((Handle) gNotificationStructure.nmStr);
}

// *******************************************************************************************
// ProgressIndicator.c
// *******************************************************************************************

#include "Miscellany.h"

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

extern WindowRef gWindowRef;
extern RGBColor  gWhiteColour;

// ***************************************************************************** doProgressBar

void  doProgressBar(void)
{
  DialogRef  dialogRef;
  RgnHandle  visRegionHdl = NewRgn();
  ControlRef progressBarRef;
  SInt16     statusMax, statusCurrent;
  SInt16     a, b, c;
  Handle     soundHdl;
  Rect       portRect, theRect;
  RGBColor   redColour = { 0xFFFF, 0x0000, 0x0000 };
  
  if(!(dialogRef = GetNewDialog(rDialog,NULL,(WindowRef) -1)))
    ExitToShell();

  SetPortDialogPort(dialogRef);
  GetPortVisibleRegion(GetWindowPort(GetDialogWindow(dialogRef)),visRegionHdl);
  UpdateControls(GetDialogWindow(dialogRef),visRegionHdl);
  QDFlushPortBuffer(GetDialogPort(dialogRef),NULL);

  SetPortWindowPort(gWindowRef);
  GetWindowPortBounds(gWindowRef,&portRect);

  GetDialogItemAsControl(dialogRef,iProgressIndicator,&progressBarRef);

  statusMax = 3456;
  statusCurrent = 0;
  SetControlMaximum(progressBarRef,statusMax);

  for(a=0;a<9;a++)
  {
    for(b=8;b<423;b+=18)
    {
      for(c=8;c<286;c+=18)
      {
        if(CheckEventQueueForUserCancel())
        {
          soundHdl = GetResource('snd ',rBarkSound);
          SndPlay(NULL,(SndListHandle) soundHdl,false);
          ReleaseResource(soundHdl);
          DisposeDialog(dialogRef);

          EraseRect(&portRect);
          MoveTo(10,292);
          RGBForeColor(&gWhiteColour);
          DrawString("\pOperation cancelled at user request");

          return;
        }
        
        SetRect(&theRect,b+a,c+a,b+17-a,c+17-a);
        if(a < 3)                 RGBForeColor(&gWhiteColour);
        else if(a > 2 && a < 6)  RGBForeColor(&redColour);
        else if(a > 5)           RGBForeColor(&gWhiteColour);
        FrameRect(&theRect);

        QDFlushPortBuffer(GetWindowPort(gWindowRef),NULL);
        QDFlushPortBuffer(GetDialogPort(dialogRef),NULL);

        SetControlValue(progressBarRef,statusCurrent++);
      }
    }
  }

  DisposeRgn(visRegionHdl);
  DisposeDialog(dialogRef);  
  EraseRect(&portRect);
  MoveTo(10,292);
  RGBForeColor(&gWhiteColour);
  DrawString("\pOperation completed");
}

// *******************************************************************************************
// ColourPicker.c
// *******************************************************************************************

#include "Miscellany.h"

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

RGBColor         gInColour = { 0xCCCC, 0x0000, 0x0000 };
RGBColor         gOutColour;
Boolean          gColorPickerButton;
extern WindowRef gWindowRef;
extern RGBColor  gWhiteColour;
extern RGBColor  gBlueColour;

// **************************************************************************** doColourPicker

void  doColourPicker(void)
{
  Rect   portRect, theRect;
  Point  where;
  Str255 prompt = "\pChoose a rectangle colour:";

  GetWindowPortBounds(gWindowRef,&portRect);
  theRect = portRect;

  RGBBackColor(&gBlueColour);
  EraseRect(&theRect);
  InsetRect(&theRect,55,55);
  RGBForeColor(&gInColour);
  PaintRect(&theRect);

  where.v = where.h = 0;

  gColorPickerButton = GetColor(where,prompt,&gInColour,&gOutColour);

  InvalWindowRect(gWindowRef,&portRect);
}

// ******************************************************************* doDrawColorPickerChoice

void  doDrawColourPickerChoice(void)
{
  Rect portRect;
  char *cString;  

  GetWindowPortBounds(gWindowRef,&portRect);
  InsetRect(&portRect,55,55);

  if(gColorPickerButton)
  {
    RGBForeColor(&gOutColour);
    PaintRect(&portRect);

    RGBForeColor(&gWhiteColour);

    MoveTo(55,22);
    DrawString("\pRequested Red Value: ");
    cString = doDecimalToHexadecimal(gOutColour.red);
    MoveTo(170,22);
    DrawText(cString,0,6);

    MoveTo(55,35);
    DrawString("\pRequested Green Value: ");
    cString = doDecimalToHexadecimal(gOutColour.green);
    MoveTo(170,35);
    DrawText(cString,0,6);

    MoveTo(55,48);
    DrawString("\pRequested Blue Value: ");
    cString = doDecimalToHexadecimal(gOutColour.blue);
    MoveTo(170,48);
    DrawText(cString,0,6);
  }
  else
  {
    RGBForeColor(&gInColour);
    PaintRect(&portRect);

    RGBForeColor(&gWhiteColour);
    MoveTo(55,48);
    DrawString("\pCancel button was clicked.");
  }
}

// ******************************************************************** doDecimalToHexadecimal

char  *doDecimalToHexadecimal(UInt16 decimalNumber)
{
  static char cString[] = "0xXXXX";
  char        *hexCharas = "0123456789ABCDEF";
  SInt16      a;

  for (a=0;a<4;decimalNumber >>= 4,++a)
    cString[5 - a] = hexCharas[decimalNumber & 0xF];

  return cString;
}

// *******************************************************************************************
// MultiMonitor.c
// *******************************************************************************************

#include "Miscellany.h"

// **************************************************************************** deviceLoopDraw

void  deviceLoopDraw(SInt16 depth,SInt16 deviceFlags,GDHandle targetDeviceHdl,SInt32 userData)
{
  RGBColor  oldForeColour;
  WindowRef windowRef;
  Rect      portRect;
  RGBColor  greenColour  = { 0x0000, 0xAAAA, 0x1111 };
  RGBColor  redColour    = { 0xAAAA, 0x4444, 0x3333 };
  RGBColor  blueColour   = { 0x5555, 0x4444, 0xFFFF };
  RGBColor  ltGrayColour = { 0xDDDD, 0xDDDD, 0xDDDD };
  RGBColor  grayColour   = { 0x9999, 0x9999, 0x9999 };
  RGBColor  dkGrayColour = { 0x4444, 0x4444, 0x4444 };
  
  GetForeColor(&oldForeColour);

  windowRef = (WindowRef) userData;
  GetWindowPortBounds(windowRef,&portRect);
  EraseRect(&portRect);

  if(((1 << gdDevType) & deviceFlags) != 0)
  {
    InsetRect(&portRect,50,50);
    RGBForeColor(&greenColour);
    PaintRect(&portRect);
    InsetRect(&portRect,40,40);
    RGBForeColor(&redColour);
    PaintRect(&portRect);
    InsetRect(&portRect,40,40);
    RGBForeColor(&blueColour);
    PaintRect(&portRect);
  }
  else
  {
    InsetRect(&portRect,50,50);
    RGBForeColor(<GrayColour);
    PaintRect(&portRect);
    InsetRect(&portRect,40,40);
    RGBForeColor(&grayColour);
    PaintRect(&portRect);
    InsetRect(&portRect,40,40);
    RGBForeColor(&dkGrayColour);
    PaintRect(&portRect);
  }

  RGBForeColor(&oldForeColour);
}

// *******************************************************************************************
// HelpTag.c
// *******************************************************************************************

#include "Miscellany.h"
#include <string.h>

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

extern ControlRef gBevelButtonControlRef;
extern WindowRef  gWindowRef;

// .......................................................................... doHelpTagControl

void  doHelpTagControl(void)
{
  HMHelpContentRec helpContent;

  memset(&helpContent,0,sizeof(helpContent));
  HMSetTagDelay(50);

  helpContent.version = kMacHelpVersion;
  helpContent.tagSide = kHMOutsideBottomLeftAligned;

  helpContent.content[kHMMinimumContentIndex].contentType = kHMStringResContent;
  helpContent.content[kHMMinimumContentIndex].u.tagStringRes.hmmResID = 129;
  helpContent.content[kHMMinimumContentIndex].u.tagStringRes.hmmIndex = 1;
  helpContent.content[kHMMaximumContentIndex].contentType = kHMStringResContent;
  helpContent.content[kHMMaximumContentIndex].u.tagStringRes.hmmResID = 129;
  helpContent.content[kHMMaximumContentIndex].u.tagStringRes.hmmIndex = 2;

  HMSetControlHelpContent(gBevelButtonControlRef,&helpContent);
}

// ........................................................................... doHelpTagWindow

void  doHelpTagWindow(void)
{
  Rect              hotRect;
  HMHelpContentRec  helpContent;

  memset(&helpContent,0,sizeof(helpContent));
  HMSetTagDelay(500);

  helpContent.version = kMacHelpVersion;
  helpContent.tagSide = kHMOutsideRightCenterAligned;
  
  GetWindowPortBounds(gWindowRef,&hotRect);
  LocalToGlobal(&topLeft(hotRect));
  LocalToGlobal(&botRight(hotRect));  
  helpContent.absHotRect = hotRect;

  helpContent.content[kHMMinimumContentIndex].contentType = kHMStringResContent;
  helpContent.content[kHMMinimumContentIndex].u.tagStringRes.hmmResID = 129;
  helpContent.content[kHMMinimumContentIndex].u.tagStringRes.hmmIndex = 3;
  helpContent.content[kHMMaximumContentIndex].contentType = kHMStringResContent;
  helpContent.content[kHMMaximumContentIndex].u.tagStringRes.hmmResID = 129;
  helpContent.content[kHMMaximumContentIndex].u.tagStringRes.hmmIndex = 4;

  HMSetWindowHelpContent(gWindowRef,&helpContent);
}

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

Demonstration Program Miscellany Comments

When this program is run, the user should make choices from the Demonstration menu, taking the
following actions and making the following observations:

o Choose the Notification item and, observing the instructions in the window, click the desktop
  immediately to make the Finder the foreground application.  A notification will be posted by
  Miscellany about 10 seconds after the Notification item choice is made.  Note that, when
  about 10 seconds have elapsed, the Notification Manager invokes an alert (Mac OS 8.6), 
  floating window (Mac OS 9.x), or system movable modal alert (Mac OS X) and alternates the
  Finder and Miscellany icons in the OS 8/9 Application menu title.  Observing the instructions
  in the alert/floating window/system movable modal alert:

o Dismiss the alert (Mac OS 8.6 only).

o On Mac OS 8/9, then choose the Miscellany item in the OS 8/9 Application menu, noting the 
  diamond mark to the left of the item name.  When Miscellany comes to the foreground, note
  that the icon alternation concludes and that an alert (invoked by Miscellany) appears. 
  Dismiss this second alert.

o On Mac OS X, click on the application's icon in the Dock.

o Choose the Notification item again and, this time, leave Miscellany in the foreground.  
  Note that only the alert invoked by Miscellany appears on this occasion.

o Choose the Notification item again and, this time, click on the desktop and then in the 
  Miscellany window before 10 seconds elapse.  Note again that only the alert invoked by
  Miscellany appears.

o Choose the Determinate Progress Indicator item, noting that the progress indicator dialog is
  automatically disposed of when the (simulated) time-consuming task concludes.

o Choose the Determinate Progress Indicator item again, and this time press the Command-period
  key combination before the (simulated) time-consuming task concludes.  Note that the progress
  indicator dialog is disposed of when the Command-period key combination is pressed.

o Choose the Colour Picker item and make colour choices using the various available modes. 
  Note that, when the Colour Picker is dismissed by clicking the OK button, the requested RGB
  colour values for the chosen colour are displayed in hexadecimal, together with a rectangle
  in that colour, in the Miscellany window.

o Choose the Multiple Monitors Draw item, noting that the drawing of the simple demonstration
  image is optimised as follows:

o On a monitor set to display 256 or more colours, the image is drawn in three distinct
  colours.  The luminance of the three colours is identical, meaning that, if these colours are
  drawn on a grayscale screen, they will all appear in the same shade of gray.

o On a monitor set to display 256 shades of gray, the image is drawn in three distinct shades
  of gray.

o Choose the Help Tags item, hover the cursor over the window and, when the Help tag appears,
  press the Command key to observe the maximum content version of the tag.  Repeat this while
  hovering the cursor over the bevel button control.

Miscellany.c

Global Variables

gDeviceLoopDrawUPP will be assigned a universal procedure pointer to the image-optimising
drawing function deviceLoopDraw called by DeviceLoop.  gProcessSerNum will be assigned the
process serial number of the Miscellany application.

main

The call to NewDeviceLoopDrawingProc creates a universal procedure pointer to the
image-optimising drawing function deviceLoopDraw.

A timer is installed and set to fire every one second.  When it fires, the function doIdle is
called.

A bevel button control is created, following which the calls to doHelpTagControl and
doHelpTagWindow create Help tags for the bevel button control and the window. 
HMSetHelpTagsDisplayed is called to disable the tags until the Help Tags item is chosen from
the Demonstration menu.

GetCurrentProcess gets the process serial number of this process.  The timer and the process
serial number are used in the notification demonstration.

appEventHandler

When the kEventAppActivated event type is received, if the global variable gNotificationInQueue
is set to true, doDisplayMessageToUser is called.  This is part of the notification
demonstration.

windowEventHandler

When the kEventWindowDrawContent event type is received, if the Multiple Monitors Draw item in
the Demonstration menu has been chosen (gMultiMonitorsDrawDemo is true), a call is made to
DeviceLoop and the universal procedure pointer to the application-defined (callback) drawing
function deviceLoopDraw is passed as the second parameter.

doMenuChoice

When the Multiple Monitors Draw item in the Demonstration menu is chosen, the window's port
rectangle is invalidated so as to force a kEventWindowDrawContent event and consequential call
to DeviceLoop.

Notification.c

doSetUpNotification

doSetUpNotification is called when the user chooses Notification from the Demonstration menu.

The first line calls doPrepareNotificationStructure, which fills in the relevant fields of a
notification structure.  The next line assigns true to a global variable which records that the
Notification item has been chosen by the user.

The next line saves the system tick count at the time that the user chose the Notification
item.  This value is used later to determine when 10 seconds have elapsed following the
execution of this line.

doPrepareNotificationStructure

doPrepareNotificationStructure fills in the relevant fields of the notification structure.

First, however, GetIconSuite creates an icon suite based on the specified resource ID and the
third parameter, which limits the suite to 'ics#', 'ics4' and 'ics8' icons.  The GetIconSuite
call returns the handle to the suite in its first parameter.  The call to GetResource loads the
specified 'snd ' resource.  GetString loads the specified 'STR ' resource.

The first line of the main block specifies the type of operating system queue.  The next line
specifies that the ¨ mark is to appear next to the application's name in the Mac OS 8/9
Application menu.  The next three lines assign the icon suite (for Mac OS 8/9), sound (for Mac
OS 8/9) and string handles previously obtained.  The next line specifies that no response
function is required to be executed when the notification is posted.

doIdle

doIdle is called when the installed timer fires.

If the user has not just chosen the Notification item in the Demonstration menu
(gNotificationDemoInvoked is false), doIdle simply returns immediately.

If, however, that item has just been chosen, and if 10 seconds (600 ticks) have elapsed since
that choice was made, the following occurs:

o The calls to GetFrontProcess and SameProcess determine whether the current foreground process
  is Miscellany.  If it is not, the notification request is installed in the notification queue
  by NMInstall and the global variable gNotificationInQueue is set to indicate that a request 
  has been placed in the queue by Miscellany.  (This latter causes doDisplayMessageToUser to be
  called when the kEventAppActivated event is received.  doDisplayMessageToUser removes the
  notification request from the queue and has Miscellany convey the required message to the
  user.)  Also, gNotificationDemoInvoked is set to false so as to ensure that the main if block
  only executes once after the Notification item is chosen.

o If, however, the current foreground process is Miscellany, the function
  doDisplayMessageToUser is called to present the required message to the user in the normal
  way.  Once again gNotificationDemoInvoked is reset to false so as to ensure that the main if 
  block only executes once after the Notification item is chosen.

doDisplayMessageToUser

doDisplayMessageToUser is called by appEventHandler and doIdle in the circumstances previously
described.

If a Miscellany notification request is in the queue, NMRemove removes it from the queue and
gNotificationInQueue is set to false to reflect this condition.  (Recall that, if the nmResp
field of the notification structure is not assigned -1, the application itself must remove the
queue element from the queue.)

Regardless of whether there was a notification in the queue or not, Miscellany then presents
its alert.  When the alert is dismissed, the notification's icon suite, sound and string
resources are released/disposed of.

ProgressBar.c

doProgressBar

doProgressBar is called when the user chooses Determinate Progress Indicator from the
Demonstration menu.

GetNewDialog creates a modal dialog.  The call to GetDialogItemAsControl retrieves the dialog's
progress indicator control.  SetControlMaximum sets the control's maximum value to equate to
the number of steps in a simulated time-consuming task.

The main for loop performs the simulated time-consuming task, represented to the user by the
drawing of a large number of coloured rectangles in the window.  The task involves 3456 calls
to FrameRect.

Within the inner for loop, CheckEventQueueForCancel is called to check whether the user has
pressed the Command-period key.  If so, a 'snd ' resource is loaded, played, and released, the
dialog is disposed of, an advisory message in drawn in the window, and the function returns.

Each time round around the inner for loop, a progress indicator control's value is incremented.

When the outer for loop exits (that is, when the Command-period key combination is not pressed
before the simulated time-consuming task completes), the dialog is disposed of.

ColourPicker.c

doColourPicker

doColourPicker is called when the user chooses Colour Picker from the Demonstration menu.

The first block erases the window's content area and paints a rectangle in the colour that will
be passed in GetColor's inColor parameter. 

The next line assigns 0 to the fields of the Point variable to be passed in GetColor's where
parameter.  ((0,0) will cause the Colour Picker dialog to be centred on the main screen.)

The call to GetColor displays the Colour Picker's dialog.  GetColor retains control until the
user clicks either the OK button or the Cancel button, at which time the port rectangle is
invalidated, causing the function doDrawColourPickerChoice to be called.

doDrawColourPickerChoice

If the user clicked the OK button, a filled rectangle is painted in the window in the colour
returned in GetColor's outColor parameter, and the values representing the red, green, and blue
components of this colour are displayed at the top of the window in hexadecimal.  Note that the
function doDecimalToHexadecimal is called to convert the decimal (UInt32) values in the fields
of the RGBColor variable outColor to hexadecimal.

If the user clicks the Cancel button, a filled rectangle is painted in the window in the colour
passed in GetColor's inColor parameter.

doDecimalToHexadecimal

doDecimalToHexadecimal converts a UInt16 value to a hexadecimal string.

MultiMonitor.c

deviceLoopDraw

deviceLoopDraw is the image-optimising drawing function the universal procedure pointer to
which is passed in the second parameter in the DeviceLoop call.  (Recall that the DeviceLoop
call is made whenever the Multiple Monitors Draw item in the Demonstration menu has been
selected and an kEventDrawContent event type is received.)  DeviceLoop scans all active video
devices, calling deviceLoopDraw whenever it encounters a device which intersects the drawing
region, and passing certain information to deviceLoopDraw.

The second line casts the SInt32 value received in the userData parameter to a WindowRef.  The
window's content area is then erased.

If an examination of the device's attributes, as received in the deviceFlags formal parameter,
reveals that the device is a colour device, three rectangles are painted in the window in three
different colours.  (The luminance value of these colours is the same, meaning that the
rectangles would all be the same shade of gray if they were drawn on a monochrome (grayscale)
device.) 

If the examination of the device's attributes reveals that the device is a monochrome device,
the rectangles are painted in three distinct shades of gray.

HelpTag.c

doHelpTagControl and doHelpTagWindow

doHelpTagControl and doHelpTagWindow create Help tags for the bevel button control and the
window.

The call to memset clears the specified block of memory.  The call to HMSetTagDelay sets the
delay, in milliseconds, before the tag opens.

For the bevel button, the tagSide field of the HMHelpContentRec structure is assigned a value
which will cause the control's tag to be displayed below the control with its left side aligned
with the left side of the button.  For the window, the tagSide field is assigned a value which
will cause the control's tag to be displayed on the window's right, centered vertically.

The main block sets the content type and retrieves and assigns the minimum and maximum content
strings from a 'STR#' resource.  The calls to HMSetControlHelpContent and
HMSetWindowHelpContent install the Help tags on the control and window.
 

Community Search:
MacTech Search:

Software Updates via MacUpdate

Macs Fan Control 1.3.1.0 - Monitor and c...
Macs Fan Control allows you to monitor and control almost any aspect of your computer's fans, with support for controlling fan speed, temperature sensors pane, menu-bar icon, and autostart with... Read more
NetShade 6.3.1 - Browse privately using...
NetShade is an anonymous proxy and VPN app+service for Mac. Unblock your Internet through NetShade's high-speed proxy and VPN servers spanning seven countries. NetShade masks your IP address as you... Read more
Dragon Dictate 4.0.7 - Premium voice-rec...
With Dragon Dictate speech recognition software, you can use your voice to create and edit text or interact with your favorite Mac applications. Far more than just speech-to-text, Dragon Dictate lets... Read more
Persecond 1.0.2 - Timelapse video made e...
Persecond is the easy, fun way to create a beautiful timelapse video. Import an image sequence from any camera, trim the length of your video, adjust the speed and playback direction, and you’re done... Read more
GIMP 2.8.14p2 - Powerful, free image edi...
GIMP is a multi-platform photo manipulation tool. GIMP is an acronym for GNU Image Manipulation Program. The GIMP is suitable for a variety of image manipulation tasks, including photo retouching,... Read more
Sandvox 2.10.2 - Easily build eye-catchi...
Sandvox is for Mac users who want to create a professional looking website quickly and easily. With Sandvox, you don't need to be a Web genius to build a stylish, feature-rich, standards-compliant... Read more
LibreOffice 5.0.1.2 - Free, open-source...
LibreOffice is an office suite (word processor, spreadsheet, presentations, drawing tool) compatible with other major office suites. The Document Foundation is coordinating development and... Read more
f.lux 36.1 - Adjusts the color of your d...
f.lux makes the color of your computer's display adapt to the time of day, warm at night and like sunlight during the day. Ever notice how people texting at night have that eerie blue glow? Or wake... Read more
VirtualBox 5.0.2 - x86 virtualization so...
VirtualBox is a family of powerful x86 virtualization products for enterprise as well as home use. Not only is VirtualBox an extremely feature rich, high performance product for enterprise customers... Read more
File Juicer 4.43 - Extract images, video...
File Juicer is a drag-and-drop can opener and data archaeologist. Its specialty is to find and extract images, video, audio, or text from files which are hard to open in other ways. In computer... Read more

ReBoard: Revolutionary Keyboard (Utilit...
ReBoard: Revolutionary Keyboard 1.0 Device: iOS Universal Category: Utilities Price: $1.99, Version: 1.0 (iTunes) Description: Do everything within the keyboard without switching apps! If you are in WhatsApp, how do you schedule a... | Read more »
Tiny Empire (Games)
Tiny Empire 1.1.3 Device: iOS Universal Category: Games Price: $2.99, Version: 1.1.3 (iTunes) Description: Launch cannonballs and blow tiny orcs into thousands of pieces in this intuitive fantasy-themed puzzle shooter! Embark on an... | Read more »
Astropad Mini (Productivity)
Astropad Mini 1.0 Device: iOS iPhone Category: Productivity Price: $4.99, Version: 1.0 (iTunes) Description: *** 50% off introductory price! ​*** Get the high-end experience of a Wacom tablet at a fraction of the price with Astropad... | Read more »
Emo Chorus (Music)
Emo Chorus 1.0.0 Device: iOS Universal Category: Music Price: $1.99, Version: 1.0.0 (iTunes) Description: Realistic Choir simulator ranging from simple Chorus emulation to full ensemble Choir with 128 members. ### introductory offer... | Read more »
Forest Spirit (Games)
Forest Spirit 1.0.5 Device: iOS Universal Category: Games Price: $2.99, Version: 1.0.5 (iTunes) Description: | Read more »
Ski Safari 2 (Games)
Ski Safari 2 1.0 Device: iOS Universal Category: Games Price: $1.99, Version: 1.0 (iTunes) Description: The world's most fantastical, fun, family-friendly skiing game is back and better than ever! Play as Sven's sister Evana, share... | Read more »
Lara Croft GO (Games)
Lara Croft GO 1.0.47768 Device: iOS Universal Category: Games Price: $4.99, Version: 1.0.47768 (iTunes) Description: Lara Croft GO is a turn based puzzle-adventure set in a long-forgotten world. Explore the ruins of an ancient... | Read more »
Whispering Willows (Games)
Whispering Willows 1.23 Device: iOS Universal Category: Games Price: $4.99, Version: 1.23 (iTunes) Description: **LAUNCH SALE 50% OFF** - Whispering Willows is on sale for 50% off ($4.99) until September 9th. | Read more »
Calvino Noir (Games)
Calvino Noir 1.1 Device: iOS iPhone Category: Games Price: $3.99, Version: 1.1 (iTunes) Description: The film noir stealth game. Calvino Noir is the exploratory, sneaking adventure through the 1930s European criminal underworld.... | Read more »
Angel Sword (Games)
Angel Sword 1.0 Device: iOS Universal Category: Games Price: $6.99, Version: 1.0 (iTunes) Description: Prepare to adventure in the most epic full scale multiplayer 3D RPG for mobile! Experience amazing detailed graphics in full HD.... | Read more »

Price Scanner via MacPrices.net

iPad Air 2 on sale for up to $100 off MSRP
Best Buy has iPad Air 2s on sale for up to $100 off MSRP on their online store for a limited time. Choose free shipping or free local store pickup (if available). Sale prices available for online... Read more
MacBook Airs on sale for $100 off MSRP
Best Buy has MacBook Airs on sale for $100 off MSRP on their online store. Choose free shipping or free local store pickup (if available). Sale prices for online orders only, in-store prices may vary... Read more
Big Grips Lift Handle For iPad Air and iPad A...
KEM Ventures, Inc. which pioneered the extra-large, super-protective iPad case market with the introduction of Big Grips Frame and Stand in 2011, is launching Big Grips Lift featuring a new super-... Read more
Samsung Launches Galaxy Tab S2, Its Most Powe...
Samsung Electronics America, Inc. has announced the U.S. release of the Galaxy Tab S2, its thinnest, lightest, ultra-fast tablet. Blending form and function, elegant design and multitasking power,... Read more
Tablet Screen Sizes Expanding as iPad Pro App...
Larger screen sizes are gaining favor as the tablet transforms into a productivity device, with shipments growing 185 percent year-over-year in 2015. According to a new Strategy Analytics’ Tablet... Read more
Today Only: Save US$50 on Adobe Elements 13;...
Keep the memories. lose the distractions. Summer’s winding down and it’s time to turn almost perfect shots into picture perfect memories with Elements 13. And get the power to edit both photos and... Read more
1.4GHz Mac mini on sale for $449, save $50
Best Buy has the 1.4GHz Mac mini on sale for $50 off MSRP on their online store. Choose free shipping or free local store pickup (if available). Price for online orders only, in-store price may vary... Read more
12-inch 1.1GHz Gold MacBook on sale for $1149...
B&H Photo has the 12″ 1.1GHz Gold Retina MacBook on sale for $1149.99 including free shipping plus NY sales tax only. Their price is $150 off MSRP, and it’s the lowest price available for this... Read more
27-inch 3.3GHz 5K iMac on sale for $1849, sav...
Best Buy has the 27″ 3.3GHz 5K iMac on sale for $1849.99. Their price is $150 off MSRP, and it’s the lowest price available for this model. Choose free shipping or free local store pickup (if... Read more
Worldwide Tablet Shipments Expected to Declin...
Does Apple badly need a touchscreen convertible/hybrid laptop MacBook? Yes, judging from a new market forecast from the International Data Corporation (IDC) Worldwide Quarterly Tablet Tracker, which... Read more

Jobs Board

*Apple* Music, Business Operations - Apple (...
**Job Summary** This role in Apple Music and in iTunes is working with…the songs that we all enjoy listening to in Apple Music. Your job will be to work wit Read more
Hardware Systems Integration Engineer - *App...
**Job Summary** We are seeking an enthusiastic electrical engineer for the Apple Watch team. This is a design engineering position that entails working with Read more
Engineering Project Manager - *Apple* TV -...
**Job Summary** The iTunes Apps project management team oversees iTunes, Apple TV, DRM and iOS Applications. We are looking for a project manager to help manage and 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* Retail Online Store: Customer Insigh...
**Job Summary** Apple Retail (Online Store) is seeking an experienced e-commerce analytics professional to join the Customer Insights Team. The Web e-Commerce Analyst Read more
All contents are Copyright 1984-2011 by Xplain Corporation. All rights reserved. Theme designed by Icreon.