home *** CD-ROM | disk | FTP | other *** search
/ MacFormat 1995 January / macformat-020.iso / Shareware City / Developers / Control Panel 0.9.4 / MyControlPanel.c < prev    next >
Encoding:
Text File  |  1994-02-02  |  26.1 KB  |  824 lines  |  [TEXT/KAHL]

  1. /*
  2.     MyControlPanel.c
  3.  
  4.     Written by Ken Worley, 02/01/94, using Symantec Think C 6.0.1. Copyright 1994.
  5.     
  6.     Feel free to use this code in a control panel of your own.  Please don't
  7.     publish or distribute this source code without giving me proper credit.
  8.     
  9.     This control panel uses no global variables, so it's not necessary
  10.     to set up and restore A4.  All of our 'global' data is in the shared data
  11.     structure (in a handle to a block in the system heap).
  12.     
  13.     The Control Panel Manager sends messages to your control panel through
  14.     its main routine when it is opened, closed, or manipulated in any way that you
  15.     would need to respond to.
  16.     
  17.     The routines already set up here will handle ALL of the messages that
  18.     would be received.  Most of them, at the present time, don't do anything
  19.     since this is only an example.  By simply inserting code into the routines,
  20.     however, you can add functionality.
  21.     
  22.     The three most common messages received are:
  23.     
  24.         initDev        We receive this when the user opens our control panel (or
  25.                     selects it in the scrolling list of control panels in System 6).
  26.         
  27.         closeDev    We receive this when the user closes the control panel (or
  28.                     selects a different control panel in System 6).
  29.                     
  30.         hitDev        The user has manipulated a control in the control panel (i.e.
  31.                     pressed a button or clicked in a text field, etc.)
  32.                     
  33.         Other messages are received when the user selects items in the Edit menu,
  34.         when the control panel is sent to the background or brought to the foreground,
  35.         when the user types, and when the control panel needs to be updated.  Controls
  36.         in the panel's DITL (item list) are updated automatically.
  37.         
  38.     The cdevValue parameter of main is a mechanism that allows you to store data
  39.     across calls to the control panel.  Normally, when an initDev message is received,
  40.     we would allocate a new handle and return the handle as the function's
  41.     return value (unless an error occurred).  The next time main is called by the
  42.     Control Panel Manager, the same value is passed back to us in cdevValue so that
  43.     we can access the memory.  We don't need to actually allocate anything here, but
  44.     we still use the mechanism to retain the address of our shared data structure
  45.     between calls.  When a closeDev message is received, we dispose of
  46.     the memory block and return cdevUnset to indicate no handle is allocated.
  47.     
  48.     Other possible return values are:
  49.     
  50.         cdevUnset    Control Panel Manager need not keep track of any memory
  51.         cdevGenErr    generic error - no error dialog is shown but panel does not load
  52.         cdevMemErr    not enough memory to continue - error dialog shown
  53.         cdevResErr    a resource is unavailable - error dialog shown
  54.         A handle to some memory for the Control Panel Manager to keep track of
  55.             between calls.
  56.     
  57.     Instead of allocating new memory, we look up the address of our shared memory
  58.     structure in a resource created by the extension code.  We use the cdevValue
  59.     mechanism to save that as long as the control panel is open.  This memory
  60.     was initially allocated by the extension code (which stored the address
  61.     in the resource).  This resource is of type 'memA'.
  62.     
  63.     I use a resource of type 'pref' to hold the control panel's "preferences."  At
  64.     this time, the resource is a struct containing only two fields:  On and
  65.     ShowIcon.  'On' indicates whether the patch should take action when trapped to and
  66.     'ShowIcon' indicates whether the extension's icon should be shown at system
  67.     startup time.
  68.     
  69.     Because of the fact that we release our resource every time the control panel is
  70.     closed, if you need to access values manipulated by the control panel in the
  71.     patch code for example, you may want to duplicate the final values in the
  72.     shared data structure.  It would be most convenient to do this in the CloseCP
  73.     routine just before the resource is released.  I store the on/off status of
  74.     the control panel in the field 'CPon' in the shared data.  The patch code uses
  75.     this field to determine if it should take any action.  The control panel also
  76.     refers to the field 'patched' to determine if the patch was installed at
  77.     system startup.
  78.     
  79.     Any resources used by a control panel must be in the range -4064 thru -4033.
  80.     The only exception has to do with balloon help.  Of that range, -4064 thru -4049
  81.     is reserved for standard resources (and some optional resources).  You can use
  82.     -4048 thru -4033 for any resources you include for use with your control panel.
  83.     This is from the New Inside Macintosh: More Macintosh Toolbox (chapter 8).
  84.     
  85.     Coordinates in your control panel dialog:
  86.     
  87.         System 7 lets you use almost any size control panel you wish.  System 6 and
  88.         earlier (which uses the Control Panel desk accessory) requires the control
  89.         panel to be in the rectangle (-1, 87, 255, 322).  In both cases, the origin
  90.         of your control panel should be at (-1, 87).  This leaves space for the
  91.         scrolling list of icons in the Control Panel desk accessory and is left
  92.         off in System 7.
  93.     
  94.     The 'nrct' resource:
  95.     
  96.         This resource contains coordinates for rectangles within your control
  97.         panel.  The Control Panel Manager will draw a 2-pixel box around each
  98.         rectangle defined in this resource.  You may include only one rectangle
  99.         if you like (to surround the entire control panel), or you can define 
  100.         several to separate different sets of controls.  This example includes
  101.         three rectangles:  one surrounds the on and off radio buttons, another
  102.         surrounds the PICT at the top of the control panel, and another
  103.         surrounds the rest of the controls/items.  This resource should have an
  104.         ID number of -4064.  If the rectangles you define do not form a rectangle
  105.         when put together, the extra space is filled in with a gray pattern.
  106.     
  107.     The 'DITL' resource:
  108.     
  109.         This is a standard dialog item list resource that defines all the controls
  110.         and other items in your control panel.  The ID numbers you give each item
  111.         are used to identify those items in your code that responds to the hitDev
  112.         message.  This resource should have an ID number of -4064.
  113.         
  114.         NOTE:  According to the New Inside Macintosh:  More Macintosh Toolbox,
  115.         chapter 8 (Control Panels), if you use a font other than the standard 
  116.         application font (if you define an 'finf' resource), you must define
  117.         text as user items rather than static text items in order for the
  118.         control panel to run in the Control Panel Desk Accessory in System 6
  119.         and earlier.
  120.         
  121.     The 'ICN#' (and related) resources:
  122.         
  123.         This is simply the icon that represents the control panel in the finder.
  124.         The ICN# resource actually refers to other resources that define icons
  125.         for different screen depths and statuses.  It is sometimes referred to
  126.         as an 'icon family' resource.  This resource must have an ID number of
  127.         -4064 and must be purgeable.
  128.         
  129.         The Mac does NOT automatically draw your control panel's icon on the
  130.         screen during startup.  We use a routine called ShowIconFamily in our
  131.         extension code to do this.
  132.     
  133.     The 'mach' resource:
  134.     
  135.         This resource indicates to the Control Panel Manager what type of machine
  136.         this control panel runs on or if it needs to check with the control panel
  137.         for that.  It has these possible values (in hex, 4 bytes):
  138.         
  139.             0000 FFFF    Call control panel with macDev message.  The control panel
  140.                         will return true if it can run on this machine and false if
  141.                         it cannot.  This example code will simply return true if
  142.                         called with the macDev message.
  143.             
  144.             3FFF 0000    Runs on Mac II systems only.
  145.             
  146.             7FFF 0400    Runs on all Macs with an ADB (Apple Desktop Bus).
  147.             
  148.             FFFF 0000    Runs on all Macs.
  149.     
  150.     The 'finf' resource:
  151.     
  152.         This resource specifies a font other than the standard application font
  153.         to be used for drawing the text in your control panel.  This only works
  154.         in System 7.  In earlier systems, define text as user items instead of
  155.         static text items and draw the text in whatever font you wish.  This
  156.         resource should have an ID number of -4049.
  157.         
  158.         For purposes of this example, I did use static text items and an 'finf'
  159.         resource.  In system 6 and earlier, text will be drawn in the standard
  160.         application font.
  161.         
  162.     Of course, your control panel will need to include a file reference (FREF)
  163.     resource, bundle (BNDL) resource, and signature resource.  Refer to your
  164.     development system documentation or Inside Macintosh for information on
  165.     these resources.
  166. */
  167.  
  168.  
  169. #define    LOCKP    HLock( (Handle)myData->CPprefsRsrc )    /* lock handle to prefs rsrc */
  170. #define    UNLOCKP    HUnlock( (Handle)myData->CPprefsRsrc )    /* unlock same */
  171.  
  172. #include "SharedData.h"            /* The definition of our shared data structure. */
  173.                                 /* Includes definitions of myDataStruct, myDataPtr, */
  174.                                 /* and myDataHandle to refer to this data */
  175.  
  176. /* about box item defines */
  177.  
  178. #define    kAboutDialogID    -4048
  179. #define kAboutOKButton        1
  180. #define kAboutText            2
  181.  
  182. /* changes after restart dialog defines */
  183.  
  184. #define kRestartDialogID    -4047
  185. #define kRestartOKButton    1
  186. #define kRestartText        2
  187.  
  188. /* control panel item defines */
  189.  
  190. #define    kCPAboutButton        1
  191. #define kCPShowIconBox        2
  192. #define kCPOnRadioButton    3
  193. #define kCPOffRadioButton    4
  194.  
  195. /* control panel preferences resource defines */
  196.  
  197. #define kCPprefsRsrcType    'pref'
  198. #define    kCPprefsRsrcID        -4048    /* careful - this number is also used in the INIT */
  199.  
  200. /* shared memory address resource defines */
  201.  
  202. #define kMemAddrType        'memA'
  203. #define kMemAddrID            -4048    /* careful - this number is also used in the INIT */
  204.  
  205. typedef struct {        /* struct used to load the memory address resource */
  206.     long    theAddr;
  207. } **memAddrHdl;
  208.  
  209. /* prototypes */
  210.  
  211. pascal long    main( short message, short item, short numItems, short cpID,
  212.     EventRecord *evt, long cdevValue, DialogPtr theCP );
  213. myDataPtr    InitCP( DialogPtr theCP, short numItems );
  214. void    CloseCP( myDataPtr myData );
  215. void    Hit( myDataPtr myData, short whichItem );
  216. void    Twiddle( myDataPtr myData );
  217. void    Update( myDataPtr myData );
  218. void    Activate( myDataPtr myData );
  219. void    Deactivate( myDataPtr myData );
  220. void    KeyPress( myDataPtr myData, EventRecord *event );
  221. void    Undo( myDataPtr myData );
  222. void    Cut( myDataPtr myData );
  223. void    Copy( myDataPtr myData );
  224. void    Paste( myDataPtr myData );
  225. void    Clear( myDataPtr myData );
  226. void    About( myDataPtr myData );
  227. void    DoRestartDialog( void );
  228.  
  229. /* Functions */
  230.  
  231. pascal long    main( short message, short item, short numItems, short cpID,
  232.     EventRecord *evt, long cdevValue, DialogPtr theCP )
  233. {
  234.     myDataPtr        myData;        /* address of my shared data (shared with patch) */
  235.     long            result;        /* result to return */
  236.     char            theChar;    /* used to handle some key presses */
  237.  
  238.     /*    This function gets called every time any action is taken in this control
  239.      *    panel (including opening & closing).  If this isn't the first call to
  240.      *    the control panel (just opening), the value we need for myData should
  241.      *    be passed to us in cdevValue.
  242.      */
  243.          if ( message == initDev )
  244.              myData = NULL;
  245.          else
  246.              myData = (myDataPtr)cdevValue;
  247.          
  248.     /*    The macDev message is sent if the Mac wants to see if we should be
  249.      *    showing in the Control Panel.  Since we want to be run on any machine,
  250.      *    we do no checking; we just return true.
  251.      */
  252.      
  253.         if ( message == macDev )
  254.             return 1L;
  255.     
  256.     /*    Here, we decide what to do based on the 'message' received from the
  257.      *    Control Panel.
  258.      */
  259.      
  260.          result = (long)myData;    /* Unless there's an error, always return myData */
  261.          
  262.         switch ( message )
  263.         {
  264.             case initDev:    /* initialize - user opened this control panel */
  265.                 myData = InitCP( theCP, numItems );
  266.                 if ( myData )
  267.                     result = (long)myData;
  268.                 else
  269.                     result = cdevGenErr;    /* return error */
  270.                 break;
  271.  
  272.             case closeDev:    /* close - last call to this device before closing */
  273.                 CloseCP( myData );
  274.                 break;
  275.                 
  276.             case hitDev:    /* user has pressed mouse button on an item */
  277.                 Hit( myData, item - numItems );
  278.                 break;
  279.                 
  280.             case nulDev:    /* nothing else to report - so twiddle */
  281.                 Twiddle( myData );
  282.                 break;
  283.                 
  284.             case updateDev:    /* update panel window (redraw controls, etc.) */
  285.                 Update( myData );
  286.                 break;
  287.                 
  288.             case activDev:    /* becoming active after being in background */
  289.                 Activate( myData );
  290.                 break;
  291.                 
  292.             case deactivDev:    /* becoming inactive after being in foreground */
  293.                 Deactivate( myData );
  294.                 break;
  295.                 
  296.             case keyEvtDev:    /* user has pressed a key */
  297.                 /* Check to see if the command key was down for menu equivalents */
  298.                     if ( ( evt->what != autoKey ) && ( evt->modifiers & cmdKey ) )
  299.                     {
  300.                         theChar = ( evt->message & charCodeMask );
  301.                         switch ( theChar )
  302.                         {
  303.                             case 'z':            /* menu command equivalents */
  304.                             case 'Z':
  305.                                 Undo( myData );        /* undo */
  306.                                 break;
  307.                             case 'x':
  308.                             case 'X':
  309.                                 Cut( myData );        /* cut */
  310.                                 break;
  311.                             case 'c':
  312.                             case 'C':
  313.                                 Copy( myData );        /* copy */
  314.                                 break;
  315.                             case 'v':
  316.                             case 'V':
  317.                                 Paste( myData );    /* paste */
  318.                                 break;
  319.                         }
  320.                     }
  321.                     else
  322.                     {
  323.                         KeyPress( myData, evt );    /* process other keystroke */
  324.                     }
  325.                 break;
  326.                 
  327.             case undoDev:    /* user picked UNDO from the Edit menu */
  328.                 Undo( myData );
  329.                 break;
  330.                 
  331.             case cutDev:    /* user picked CUT from the Edit menu */
  332.                 Cut( myData );
  333.                 break;
  334.                 
  335.             case copyDev:    /* user picked COPY from the Edit menu */
  336.                 Copy( myData );
  337.                 break;
  338.                 
  339.             case pasteDev:    /* user picked PASTE from the Edit menu */
  340.                 Paste( myData );
  341.                 break;
  342.                 
  343.             case clearDev:    /* user picked CLEAR from the Edit menu */
  344.                 Clear( myData );
  345.                 break;
  346.         }
  347.     return result;
  348. }
  349.  
  350.  
  351. myDataPtr    InitCP( DialogPtr theCP, short numItems )
  352. {
  353.     short        itemType;        /* these 3 local vars that can be used to */
  354.     Handle        itemHandle;        /* manipulate items in the control     */
  355.     Rect        itemRect;        /* panel dialog */
  356.     myDataPtr    myData;            /* a pointer to our shared data structure */
  357.     
  358.     memAddrHdl    memAddr;        /* Handle to the rsrc containing the addr of our */
  359.                                 /* shared memory data structure */
  360.     CPprefsPtr    myPrefs;        /* pointer to our preferences resource struct */
  361.     
  362.     /*    At this point, the control panel has just been opened. */
  363.     
  364.     /*    Attempt to load the resource containing the addr of our shared memory struct */
  365.     
  366.         memAddr = (memAddrHdl)Get1Resource( kMemAddrType, kMemAddrID );
  367.         
  368.         if ( !memAddr )        /* could not load resource */
  369.         {
  370.             return NULL;    /* return NULL to indicate an error */
  371.         }
  372.         else
  373.         {
  374.             myData = (myDataPtr)((*memAddr)->theAddr); /* get addr of shared memory */
  375.             ReleaseResource( (Handle)memAddr );    /* release the rsrc - we have the info */
  376.         }
  377.             
  378.     /*    Wait until the data structure is not being used by someone else */
  379.     
  380.         while ( myData->inUse ) {}
  381.         
  382.     /*    Now mark the data structure as being in use by setting the inUse flag to true */
  383.     
  384.         myData->inUse = true;
  385.     
  386.     /*    Set up data structure with info about us. */
  387.     
  388.         myData->CPdialogPtr = theCP;        /* dialog pointer for the panel window */
  389.         myData->CPitems = numItems;        /* number of items in the dialog */
  390.     
  391.     /*    Load the control panel preferences resource.  Leave it unlocked except when
  392.      *    when we need to lock it.  When the control panel is closed, the resource
  393.      *    will be released.
  394.      */
  395.         
  396.         myData->CPprefsRsrc =
  397.             (CPprefsHandle)Get1Resource( kCPprefsRsrcType, kCPprefsRsrcID );
  398.         
  399.         if ( myData->CPprefsRsrc )
  400.         {
  401.             LOCKP;                                /* it's there - lock it down and */
  402.             myPrefs = (*(myData->CPprefsRsrc));    /* dereference for easy access */
  403.                                                 /* since it's locked */
  404.         }
  405.         else    /* it's not there - create a new resource */
  406.         {
  407.             myData->CPprefsRsrc =
  408.                 (CPprefsHandle)NewHandleClear( sizeof( CPprefsStruct ) );
  409.             
  410.             if ( myData->CPprefsRsrc )
  411.             {
  412.                 LOCKP;                                    /* lock the new handle */
  413.                 myPrefs = (*(myData->CPprefsRsrc));    /* dereference for easy access */
  414.                                                         /* since it's locked */
  415.                 
  416.                 myPrefs->On = true;                    /* default is to set both of */
  417.                 myPrefs->ShowIcon = true;            /* these to true */
  418.                 
  419.                 AddResource( (Handle)myData->CPprefsRsrc, kCPprefsRsrcType,
  420.                     kCPprefsRsrcID, "\pPreferences" );
  421.             }
  422.             else    /* unable to create new Handle for resource */
  423.             {
  424.                 myData->inUse = false;
  425.                 return NULL;            /* exit with an error */
  426.             }
  427.         }
  428.         
  429.     /*    Set all controls to their correct values. */
  430.     
  431.         /* Get the ON button item */
  432.         
  433.             GetDItem( myData->CPdialogPtr, kCPOnRadioButton,
  434.                 &itemType, &itemHandle, &itemRect );
  435.                 
  436.             if ( myPrefs->On )
  437.                 SetCtlValue( (ControlHandle)itemHandle, 1 );
  438.             else
  439.                 SetCtlValue( (ControlHandle)itemHandle, 0 );
  440.                 
  441.         /* Get the OFF button item */
  442.         
  443.             GetDItem( myData->CPdialogPtr, kCPOffRadioButton,
  444.                 &itemType, &itemHandle, &itemRect );
  445.                 
  446.             if ( myPrefs->On )
  447.                 SetCtlValue( (ControlHandle)itemHandle, 0 );
  448.             else
  449.                 SetCtlValue( (ControlHandle)itemHandle, 1 );
  450.                 
  451.         /* Get the Show Icon check box item */
  452.         
  453.             GetDItem( myData->CPdialogPtr, kCPShowIconBox,
  454.                 &itemType, &itemHandle, &itemRect );
  455.             
  456.             if ( myPrefs->ShowIcon )
  457.                 SetCtlValue( (ControlHandle)itemHandle, 1 );
  458.             else
  459.                 SetCtlValue( (ControlHandle)itemHandle, 0 );
  460.     
  461.     /*    Unlock the prefs rsrc, but don't allow it to be purged */
  462.     
  463.         HNoPurge( (Handle)myData->CPprefsRsrc );
  464.         UNLOCKP;
  465.  
  466.     /*    Done with the data structure for now */
  467.     
  468.         myData->inUse = false;
  469.     
  470.     return myData;
  471. }
  472.  
  473.  
  474. void    CloseCP( myDataPtr myData )
  475. {
  476.     /*    Here, we would want to destroy anything we created while the control panel
  477.      *    was "up."  The only thing left should be the shared data structure (which
  478.      *    we never destroy).  Leaving things lying around in memory can only lead to
  479.      *    system bombs.  If we wanted to save any settings to disk, this would
  480.      *    be the place to do it.
  481.      */
  482.      
  483.      CPprefsHandle        prefsHandle;
  484.      
  485.      /* Wait until our data structure is not in use */
  486.      
  487.          while ( myData->inUse ) {}
  488.          
  489.      /* Now that it's free, mark it as in use for us */
  490.      
  491.          myData->inUse = true;
  492.      
  493.      /* Write our preferences resource back to the resource file */
  494.      
  495.          prefsHandle = myData->CPprefsRsrc;
  496.          ChangedResource( (Handle)prefsHandle );
  497.          WriteResource( (Handle)prefsHandle );
  498.      
  499.      /* Save the on/off status of the control panel in the CPon field of the */
  500.      /* shared data structure. */
  501.      
  502.          myData->CPon = (*prefsHandle)->On;
  503.          
  504.      /* Unlock the resource and release it.  We'll reload it next time we're opened. */
  505.      
  506.          UNLOCKP;
  507.          ReleaseResource( (Handle)prefsHandle );
  508.          myData->CPprefsRsrc = NULL;
  509.          prefsHandle = NULL;
  510.          
  511.      /* Now we're through using our shared data structure */
  512.      
  513.          myData->inUse = false;
  514. }
  515.  
  516.  
  517. void    Hit( myDataPtr myData, short whichItem )
  518. {
  519.     /*    The user has pressed a button or clicked in a text editing field in the
  520.      *    control panel.  Handle the 'hit' here.
  521.      */
  522.      
  523.     short        itemType;        /* these 3 local vars that can be used to */
  524.     Handle        itemHandle;        /* manipulate items in the control     */
  525.     Rect        itemRect;        /* panel dialog */
  526.  
  527.     CPprefsHandle    prefsHandle;    /* used to more conveniently access the prefs rsrc */
  528.     
  529.     LOCKP;
  530.     prefsHandle = myData->CPprefsRsrc;
  531.     
  532.     switch ( whichItem )
  533.     {
  534.         case kCPAboutButton:
  535.             About( myData );
  536.             break;
  537.             
  538.         case kCPOnRadioButton:
  539.             if ( !(*prefsHandle)->On )    /* if off */
  540.             {
  541.                 GetDItem( myData->CPdialogPtr, kCPOnRadioButton,
  542.                     &itemType, &itemHandle, &itemRect );
  543.                 SetCtlValue( (ControlHandle)itemHandle, 1 );
  544.                 
  545.                 GetDItem( myData->CPdialogPtr, kCPOffRadioButton,
  546.                     &itemType, &itemHandle, &itemRect );
  547.                 SetCtlValue( (ControlHandle)itemHandle, 0 );
  548.                 
  549.                 (*prefsHandle)->On = true;
  550.                 
  551.                 if ( !myData->patched )
  552.                     DoRestartDialog();
  553.             }
  554.             break;
  555.             
  556.         case kCPOffRadioButton:
  557.             if ( (*prefsHandle)->On )    /* if on */
  558.             {
  559.                 GetDItem( myData->CPdialogPtr, kCPOnRadioButton,
  560.                     &itemType, &itemHandle, &itemRect );
  561.                 SetCtlValue( (ControlHandle)itemHandle, 0 );
  562.                 
  563.                 GetDItem( myData->CPdialogPtr, kCPOffRadioButton,
  564.                     &itemType, &itemHandle, &itemRect );
  565.                 SetCtlValue( (ControlHandle)itemHandle, 1 );
  566.                 
  567.                 (*prefsHandle)->On = false;
  568.             }
  569.             break;
  570.  
  571.         case kCPShowIconBox:
  572.             GetDItem( myData->CPdialogPtr, kCPShowIconBox,
  573.                 &itemType, &itemHandle, &itemRect );
  574.  
  575.             if ( (*prefsHandle)->ShowIcon )    /* if on */
  576.             {
  577.                 SetCtlValue( (ControlHandle)itemHandle, 0 );        /* turn it off */
  578.                 (*prefsHandle)->ShowIcon = false;
  579.             }
  580.             else
  581.             {
  582.                 SetCtlValue( (ControlHandle)itemHandle, 1 );        /* turn it on */
  583.                 (*prefsHandle)->ShowIcon = true;
  584.             }
  585.             break;
  586.     }
  587.     UNLOCKP;
  588. }
  589.  
  590.  
  591. void    Twiddle( myDataPtr myData )
  592. {
  593.     /*    The user isn't doing anything at the moment, so take this time to do
  594.      *    odds and ends (if needed) in this idle time.
  595.      */
  596.  
  597.  
  598. }
  599.  
  600.  
  601. void    Update( myDataPtr myData )
  602. {
  603.     /*    We need to redraw the panel because something has screwed it up (like
  604.      *    another window moved from in front of it).  This is the same as in any
  605.      *    application except we don't call BeginUpdate() and EndUpdate().  The
  606.      *    Dialog Manager should take care of redrawing any controls.
  607.      */
  608.      
  609. }
  610.  
  611.  
  612. void    Activate( myDataPtr myData )
  613. {
  614.     /*    We're becoming active either because we were just opened, or we were in
  615.      *    the background and we're being brought to the foreground.  Take care of
  616.      *    hiliting text fields or list items or whatever.
  617.      */
  618.      
  619. }
  620.  
  621.  
  622. void    Deactivate( myDataPtr myData )
  623. {
  624.     /*    We're becoming inactive because we're being sent to the background.  Take
  625.      *    care of unhiliting text fields, list items, or whatever.
  626.      */
  627.  
  628. }
  629.  
  630.  
  631. void    KeyPress( myDataPtr myData, EventRecord *event )
  632. {
  633.     /*    The user has pressed a key on the keyboard (or a combination of keys).  In
  634.      *    any case, a keyboard event has been generated.  The main routine has already
  635.      *    checked for command key menu equivalents, so any real typing is handled
  636.      *    here (possibly by passing it on to textEdit if you have text fields).
  637.      *    I saw a note from Symantec in their cdev example that said text fields don't
  638.      *    seem to work correctly in control panels, so they convert theirs to user
  639.      *    items (at least while the panel's open).  I haven't tried it.
  640.      */
  641.  
  642. }
  643.  
  644.  
  645. void    Undo( myDataPtr myData )
  646. {
  647.     /*    User has selected UNDO from the Edit menu.  Undo the last action here if
  648.      *    it's appropriate and you've implemented an undo.  Otherwise, ignore.
  649.      */
  650.  
  651.     SysBeep( 3 );
  652. }
  653.  
  654.  
  655. void    Cut( myDataPtr myData )
  656. {
  657.     /*    User has selected CUT from the Edit menu.  If you have a text field that
  658.      *    is active, pass this along to textEdit.  Otherwise, ignore.
  659.      */
  660.     
  661.     SysBeep( 3 );
  662. }
  663.  
  664.  
  665. void    Copy( myDataPtr myData )
  666. {
  667.     /*    User has selected COPY from the Edit menu.  If you have a text field that
  668.      *    is active, pass this along to textEdit.  Otherwise, ignore.
  669.      */
  670.     
  671.     SysBeep( 3 );
  672. }
  673.  
  674.  
  675. void    Paste( myDataPtr myData )
  676. {
  677.     /*    User has selected PASTE from the Edit menu.  If you have a text field that
  678.      *    is active, pass this along to textEdit.  Otherwise, ignore.
  679.      */
  680.     
  681.     SysBeep( 3 );
  682. }
  683.  
  684.  
  685. void    Clear( myDataPtr myData )
  686. {
  687.     /*    User has selected CLEAR from the Edit menu.  If you have a text field that
  688.      *    is active, pass this along to textEdit.  Otherwise, ignore.
  689.      */
  690.     
  691.     SysBeep( 3 );
  692. }
  693.  
  694. void    About( myDataPtr myData )
  695. {
  696.     /*    This routine displays an about box for this control panel. */
  697.     
  698.     WindowPtr        winMgrPort;        /* store current window mgr port here */
  699.     WindowPtr        currentPort;    /* store the current port here */
  700.     DialogPtr        aboutDlg;        /* to store our dialog in */
  701.     
  702.     short        itemType;        /* these 3 local variables are used to */
  703.     Handle        itemHandle;        /* manipulate items in the dialog.     */
  704.     Rect        itemRect;
  705.  
  706.     short        itemHit;        /* use with ModalDialog */
  707.     Point        refPt;            /* a reference point */
  708.     
  709.     /*    Get the window manager port and the current port (our control panel)
  710.      *    Then convert the upper left corner of the control panel to a global
  711.      *    point for referencing our about dialog.
  712.      */
  713.      
  714.          GetWMgrPort( &winMgrPort );
  715.          GetPort( ¤tPort );
  716.          
  717.          SetPt( &refPt, 0, 0 );
  718.          LocalToGlobal( &refPt );
  719.          refPt.h += 93;        /* move to right over actual panel */
  720.          
  721.     /*    Now, load our dialog resource, move it on top of the control panel,
  722.      *    make it the current port, then make it visible (the resource should
  723.      *    mark the dialog as NOT initially visible.
  724.      */
  725.     
  726.         aboutDlg = GetNewDialog( kAboutDialogID, NULL, (WindowPtr)-1L );
  727.         
  728.         /* This is an example - move your about dialog wherever you want */
  729.         
  730.         MoveWindow( aboutDlg, refPt.h, refPt.v, true );
  731.         
  732.         SetPort( aboutDlg );
  733.         
  734.         ShowWindow( aboutDlg );
  735.     
  736.      /*    Get the OK button item and draw a bold border around it to show that
  737.       *    it's the default button.
  738.       */
  739.      
  740.          GetDItem( aboutDlg, kAboutOKButton, &itemType, &itemHandle, &itemRect );
  741.          InsetRect( &itemRect, -4, -4 );
  742.          PenSize( 3, 3 );
  743.          FrameRoundRect( &itemRect, 16, 16 );
  744.          PenSize( 1, 1 );
  745.      
  746.      /*    Loop and call ModalDialog until the user presses the OK button */
  747.      
  748.          ModalDialog( NULL, &itemHit );
  749.          while ( itemHit != kAboutOKButton )
  750.              ModalDialog( NULL, &itemHit );
  751.          
  752.      /*    Now get rid of the dialog and set the port back to the control panel */
  753.      
  754.          DisposDialog( aboutDlg );
  755.          SetPort( currentPort );
  756. }
  757.  
  758. void    DoRestartDialog( void )
  759. {
  760.     /*    This routine displays a dialog that tells the user that changes made
  761.      *    won't take effect until after the computer is restarted.
  762.      */
  763.     
  764.     WindowPtr        winMgrPort;        /* store current window mgr port here */
  765.     WindowPtr        currentPort;    /* store the current port here */
  766.     DialogPtr        theDlg;            /* to store our dialog in */
  767.     
  768.     short        itemType;        /* these 3 local variables are used to */
  769.     Handle        itemHandle;        /* manipulate items in the dialog.     */
  770.     Rect        itemRect;
  771.  
  772.     short        itemHit;        /* use with ModalDialog */
  773.     Point        refPt;            /* a reference point */
  774.     
  775.     /*    Get the window manager port and the current port (our control panel)
  776.      *    Then convert the upper left corner of the control panel to a global
  777.      *    point for referencing our dialog.
  778.      */
  779.      
  780.          GetWMgrPort( &winMgrPort );
  781.          GetPort( ¤tPort );
  782.          
  783.          SetPt( &refPt, 0, 0 );
  784.          LocalToGlobal( &refPt );
  785.          refPt.h += 107;        /* move to right over actual panel */
  786.          refPt.v += 80;        /* also move it down some */
  787.          
  788.     /*    Now, load our dialog resource, move it on top of the control panel,
  789.      *    make it the current port, then make it visible (the resource should
  790.      *    mark the dialog as NOT initially visible.
  791.      */
  792.     
  793.         theDlg = GetNewDialog( kRestartDialogID, NULL, (WindowPtr)-1L );
  794.         
  795.         /* This is an example - move your about dialog wherever you want */
  796.         
  797.         MoveWindow( theDlg, refPt.h, refPt.v, true );
  798.         
  799.         SetPort( theDlg );
  800.         
  801.         ShowWindow( theDlg );
  802.     
  803.      /*    Get the OK button item and draw a bold border around it to show that
  804.       *    it's the default button.
  805.       */
  806.      
  807.          GetDItem( theDlg, kRestartOKButton, &itemType, &itemHandle, &itemRect );
  808.          InsetRect( &itemRect, -4, -4 );
  809.          PenSize( 3, 3 );
  810.          FrameRoundRect( &itemRect, 16, 16 );
  811.          PenSize( 1, 1 );
  812.      
  813.      /*    Loop and call ModalDialog until the user presses the OK button */
  814.      
  815.          ModalDialog( NULL, &itemHit );
  816.          while ( itemHit != kRestartOKButton )
  817.              ModalDialog( NULL, &itemHit );
  818.          
  819.      /*    Now get rid of the dialog and set the port back to the control panel */
  820.      
  821.          DisposDialog( theDlg );
  822.          SetPort( currentPort );
  823. }
  824.