home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 2000 November: Tool Chest / Dev.CD Nov 00 TC Disk 1.toast / Sample Code / Human Interface Toolbox / CustomWindow / CustomWindow.c < prev    next >
Encoding:
C/C++ Source or Header  |  2000-10-06  |  19.5 KB  |  539 lines

  1. /*
  2.     File:        CustomWindow.c    
  3.  
  4.     Contains:    A sample on how to create a fully functional custom window for Carbon
  5.  
  6.     Written by:     Karl Groethe
  7.  
  8.     Copyright:    Copyright © 2000 by Apple Computer, Inc., All Rights Reserved.
  9.  
  10.             You may incorporate this Apple sample source code into your program(s) without
  11.             restriction. This Apple sample source code has been provided "AS IS" and the
  12.             responsibility for its operation is yours. You are not permitted to redistribute
  13.             this Apple sample source code as "Apple sample source code" after having made
  14.             changes. If you're going to re-distribute the source, we require that you make
  15.             it clear in the source that the code was descended from Apple sample source
  16.             code, but that you've made changes.
  17.  
  18.     Change History (most recent first):
  19.                         6/28/00     created
  20.                 
  21.  
  22. */
  23. #include "CustomWindow.h"
  24. #include <Carbon/Carbon.h>
  25.  
  26. #define kPictureID     128
  27. #define kMaskPictureID    129
  28.  
  29. SInt32 myWindowDef(short varCode,WindowRef window, SInt16 message, SInt32 param)
  30. {
  31.     /*------------------------------------------------------
  32.         This is the main entry point for the Custom Window.
  33.     --------------------------------------------------------*/
  34.     switch(message){
  35.         case kWindowMsgDraw:
  36.                     return myWindowDraw(window,param);
  37.         case kWindowMsgHitTest:
  38.                     return myWindowHitTest(window,param);
  39.         case kWindowMsgInitialize:
  40.                     return myWindowInitialize(window,param);
  41.         case kWindowMsgCleanUp:
  42.                     return myWindowCleanUp(window,param);
  43.         case kWindowMsgDrawGrowOutline:
  44.                     return myWindowDrawGrowOutline(window,param);
  45.         //8.0 forward
  46.         case kWindowMsgGetFeatures:
  47.                     return myWindowGetFeatures(window,param);
  48.         case kWindowMsgGetRegion:
  49.                     return myWindowGetRegion(window,param);
  50.         //8.5 forward
  51.         case kWindowMsgDragHilite:
  52.                     return myWindowDragHilite(window,param);
  53.         case kWindowMsgModified:
  54.                     return myWindowModified(window,param);
  55.         case kWindowMsgDrawInCurrentPort:
  56.                     return myWindowDrawInCurrentPort(window,param);
  57.         case kWindowMsgStateChanged:
  58.                     return myWindowStateChanged(window,param);
  59.         //carbon only
  60.         case kWindowMsgGetGrowImageRegion:
  61.                    return myWindowGetGrowImageRegion(window,param);
  62.         default:
  63.                     return 0;
  64.     }
  65. }
  66. SInt32 myWindowGetFeatures(WindowRef window,SInt32 param)
  67. {
  68.     /*------------------------------------------------------
  69.         Define which options your custom window supports.
  70.     --------------------------------------------------------*/
  71.     //just enable everything for our demo
  72.     *(OptionBits*)param=kWindowCanGrow|
  73.                         kWindowCanZoom|
  74.                         kWindowCanCollapse|
  75.                         kWindowCanGetWindowRegion|
  76.                         kWindowHasTitleBar|
  77.                         kWindowSupportsDragHilite|
  78.                         kWindowCanDrawInCurrentPort|
  79.                         kWindowCanMeasureTitle|
  80.                         kWindowWantsDisposeAtProcessDeath|
  81.                         kWindowSupportsSetGrowImageRegion|
  82.                         kWindowDefSupportsColorGrafPort;    
  83.     return 1;
  84. }
  85. SInt32 myWindowDraw(WindowRef window,SInt32 param)
  86. {
  87.     /*------------------------------------------------------
  88.         Use this method to draw the window based on the value
  89.         of param.
  90.             wNoHit:         draw the frame and attributes
  91.             wInGoAway:         hilite or unhilite GoAway box
  92.             wInZoomIn:         hilite or unhilite ZoomIn Box
  93.             wInZoomOut:     hilite or unhilite ZoomOut Box
  94.             wInCollapseBox:     hilite or unhilite Collapse Box 
  95.     --------------------------------------------------------*/
  96.     static Boolean hilite=FALSE;
  97.     WindowAttributes attributes;
  98.     
  99.     if(IsWindowVisible(window))
  100.     {
  101.         switch(param){
  102.             case wNoHit:
  103.                         hilite=FALSE;//redrawn so no box hiliteing
  104.                         
  105.                         drawWindowFrame(window);
  106.                         
  107.                         GetWindowAttributes(window,&attributes);
  108.                         if(attributes & kWindowCloseBoxAttribute)//is there a close box?
  109.                             drawWindowCloseBox(window,hilite);             
  110.                         if(attributes & kWindowFullZoomAttribute)//is there a zoom box?
  111.                             drawWindowZoomBox(window,hilite);
  112.                         if(attributes & kWindowCollapseBoxAttribute)//is there a collapse box?
  113.                             drawWindowCollapseBox(window,hilite);
  114.                         
  115.                         break;
  116.             case wInGoAway: 
  117.                         hilite=drawWindowCloseBox(window,!hilite);
  118.                         break;
  119.             case wInZoomIn:
  120.             case wInZoomOut:
  121.                         hilite=drawWindowZoomBox(window,!hilite);
  122.                         break;
  123.             case wInCollapseBox:
  124.                         hilite=drawWindowCollapseBox(window,!hilite);
  125.                         break;
  126.         }
  127.     }
  128.     return 0;
  129. }
  130.  
  131. RgnHandle getWindowCloseBoxRegion(WindowRef window,RgnHandle closeBoxRegion)
  132. {
  133.     /*------------------------------------------------------
  134.         Define the region for the close box
  135.     --------------------------------------------------------*/
  136.     SetEmptyRgn(closeBoxRegion);
  137.     return closeBoxRegion;
  138. }
  139. RgnHandle getWindowZoomBoxRegion(WindowRef window,RgnHandle zoomBoxRegion)
  140. {
  141.     /*------------------------------------------------------
  142.         Define the region for the zoom box
  143.     --------------------------------------------------------*/
  144.     SetEmptyRgn(zoomBoxRegion);
  145.     return zoomBoxRegion;
  146.  
  147. }
  148. RgnHandle getWindowCollapseBoxRegion(WindowRef window,RgnHandle collapseBoxRegion)
  149. {
  150.     /*------------------------------------------------------
  151.         Define the region for the collapse box
  152.     --------------------------------------------------------*/
  153.     SetEmptyRgn(collapseBoxRegion);
  154.     return collapseBoxRegion;
  155. }
  156. RgnHandle getWindowGrowBoxRegion(WindowRef window,RgnHandle growBoxRegion)
  157. {
  158.     /*------------------------------------------------------
  159.         Define the region for the Grow Box
  160.     --------------------------------------------------------*/
  161.     SetEmptyRgn(growBoxRegion);
  162.     return growBoxRegion;
  163. }
  164. RgnHandle getWindowTitleBarRegion(WindowRef window,RgnHandle titleBarRegion)
  165. {
  166.     /*------------------------------------------------------
  167.         Define the region for the title bar
  168.     --------------------------------------------------------*/
  169.     SetEmptyRgn(titleBarRegion);
  170.     return titleBarRegion;
  171. }
  172. RgnHandle getWindowTitleTextRegion(WindowRef window,RgnHandle titleTextRegion)
  173. {
  174.     /*------------------------------------------------------
  175.         Define the region for the text in the title bar
  176.     --------------------------------------------------------*/
  177.     SetEmptyRgn(titleTextRegion);
  178.     return titleTextRegion;
  179. }
  180. RgnHandle getWindowContentRegion(WindowRef window,RgnHandle contentRegion)
  181. {
  182.     /*------------------------------------------------------
  183.         Define the content region of our window.
  184.     --------------------------------------------------------*/
  185.     SetEmptyRgn(contentRegion);
  186.     if(!IsWindowCollapsed(window)){
  187.         //only define the content region when the window is 
  188.         //not collapsed
  189.     }
  190.     
  191.     return contentRegion;
  192. }
  193. RgnHandle getWindowStructureRegion(WindowRef window, RgnHandle structureRegion)
  194. {
  195.     /*------------------------------------------------------
  196.         Define the structural region of our window.
  197.     --------------------------------------------------------*/
  198.     static RgnHandle pictureRgn=NULL;
  199.     static Rect pictureRect;
  200.     Rect windowRect;
  201.     
  202.     SetEmptyRgn(structureRegion);
  203.     
  204.     if(!pictureRgn){//haven't Cached our region yet
  205.         PicHandle myPicture=GetPicture(kMaskPictureID);
  206.         GrafPtr    origPort;
  207.         GDHandle origDev;
  208.         GWorldPtr pictMask;
  209.         PixMapHandle maskBitMap;
  210.         GetGWorld(&origPort,&origDev);
  211.         pictureRgn=NewRgn();
  212.         pictureRect=(*myPicture)->picFrame;
  213.         NewGWorld(&pictMask,1,&pictureRect,NULL,NULL,0);
  214.         maskBitMap=GetPortPixMap(pictMask);
  215.         LockPixels(maskBitMap);
  216.         SetGWorld(pictMask,NULL);
  217.         EraseRect(&pictureRect);
  218.         DrawPicture(myPicture,&pictureRect);
  219.         BitMapToRegion(pictureRgn,(BitMap*)*maskBitMap);//use the mask to create a region
  220.         InsetRgn(pictureRgn,1,1);
  221.         SetGWorld(origPort,origDev);
  222.         UnlockPixels(maskBitMap);
  223.         DisposeGWorld(pictMask);
  224.         ReleaseResource((Handle)myPicture);
  225.     }
  226.     getCurrentPortBounds(&windowRect);//how big is the window
  227.     CopyRgn(pictureRgn,structureRegion);//make a copy of our cached region
  228.     MapRgn(structureRegion,&pictureRect,&windowRect);//scale it to our actual window size
  229.     return structureRegion;
  230. }
  231.  
  232. RgnHandle getWindowDragRegion(WindowRef window, RgnHandle dragRegion)
  233. {
  234.     /*------------------------------------------------------
  235.         Define the drag region of our window.
  236.     --------------------------------------------------------*/
  237.     RgnHandle structureRegion=NewRgn();
  238.     RgnHandle contentRegion=NewRgn();
  239.     
  240.     SetEmptyRgn(dragRegion);
  241.     
  242.     getWindowStructureRegion(window,structureRegion);
  243.     getWindowContentRegion(window,contentRegion);
  244.     //our drag region is the difference between the structural and content regions
  245.     DiffRgn(structureRegion,contentRegion,dragRegion); 
  246.  
  247.     DisposeRgn(structureRegion);
  248.     DisposeRgn(contentRegion);
  249.     
  250.     return dragRegion;
  251. }
  252. void drawWindowFrame(WindowRef window)
  253. {
  254.     /*------------------------------------------------------
  255.         Draw the frame of our window.
  256.         
  257.         This function needs to draw the title bar, 
  258.         the grow box, the title string and the 
  259.         structural aspects of the window.
  260.     --------------------------------------------------------*/
  261.     static GWorldPtr framePict=NULL;
  262.     static Rect pictureRect;
  263.     GrafPtr thePort;
  264.     Rect frame;
  265.  
  266.     if(!framePict){//haven't cached our picture
  267.         PicHandle myPicture=GetPicture(kPictureID);
  268.         GrafPtr    origPort;
  269.         GDHandle origDev;
  270.         GetGWorld(&origPort,&origDev);
  271.         pictureRect=(*myPicture)->picFrame;
  272.         NewGWorld(&framePict,0,&pictureRect,NULL,NULL,0);
  273.         SetGWorld(framePict,NULL);
  274.         DrawPicture(myPicture,&pictureRect);
  275.         SetGWorld(origPort,origDev);
  276.         ReleaseResource((Handle)myPicture);
  277.     }
  278.  
  279.     getCurrentPortBounds(&frame);
  280.     GetPort(&thePort);
  281.     CopyBits(GetPortBitMapForCopyBits(framePict),
  282.              GetPortBitMapForCopyBits(thePort),
  283.              &pictureRect,&frame,srcCopy,NULL);//draw our picture
  284.     myWindowDrawGrowBox(window,0);//draw grow box as part of frame
  285.     
  286.     if(IsWindowHilited(window))
  287.     {
  288.         //do any hilighting
  289.     }
  290.     
  291. }
  292. Boolean drawWindowCloseBox(WindowRef window, Boolean hilite)
  293. {
  294.     /*------------------------------------------------------
  295.         This function draws the close box.
  296.         If hilite is true it draws the hiliting as well.
  297.     --------------------------------------------------------*/
  298.     RgnHandle closeBoxRegion=NewRgn();
  299.     getWindowCloseBoxRegion(window,closeBoxRegion);
  300.     EraseRgn(closeBoxRegion);//clear away old
  301.     //draw close box
  302.     if(hilite)
  303.     {
  304.         //do hilighting
  305.     }
  306.     DisposeRgn(closeBoxRegion);
  307.     return hilite;
  308. }
  309. Boolean drawWindowZoomBox(WindowRef window, Boolean hilite)
  310. {
  311.     /*------------------------------------------------------
  312.         This function draws the zoom box.
  313.         If hilite is true it draws the hiliting as well.
  314.     --------------------------------------------------------*/
  315.     RgnHandle zoomBoxRegion=NewRgn();
  316.     getWindowZoomBoxRegion(window,zoomBoxRegion);
  317.     EraseRgn(zoomBoxRegion);//clear away old
  318.     //draw zoom Box
  319.     if(hilite)
  320.     {
  321.         //do hilighting
  322.     }
  323.     DisposeRgn(zoomBoxRegion);
  324.     return hilite;
  325. }
  326.  
  327. Boolean drawWindowCollapseBox(WindowRef window, Boolean hilite)
  328. {
  329.     /*------------------------------------------------------
  330.         This function draws the collapse box.
  331.         If hilite is true it draws the hiliting as well.
  332.     --------------------------------------------------------*/
  333.     RgnHandle collapseBoxRegion=NewRgn();
  334.     getWindowCollapseBoxRegion(window,collapseBoxRegion);
  335.     EraseRgn(collapseBoxRegion);//clear away old stuff
  336.     if(hilite){
  337.         //do hilighting
  338.     }
  339.     DisposeRgn(collapseBoxRegion);
  340.     return hilite;
  341. }
  342. RgnHandle getWindowUpdateRegion(WindowRef window, RgnHandle updateRegion)
  343. {    
  344.     return updateRegion;
  345. }
  346. SInt32 myWindowHitTest(WindowRef window,SInt32 param)
  347. {
  348.     /*------------------------------------------------------
  349.         Determine the region of the window which was hit
  350.     --------------------------------------------------------*/
  351.     Point hitPoint;
  352.     static RgnHandle tempRgn=nil;
  353.     if(!tempRgn) tempRgn=NewRgn();
  354.   
  355.     SetPt(&hitPoint,LoWord(param),HiWord(param));//get the point clicked
  356.     
  357.     if(IsWindowHilited(window)){ //make sure the window is in front for these
  358.  
  359.         if(PtInRgn(hitPoint,getWindowGrowBoxRegion(window,tempRgn)))//in GrowBox?
  360.             return wInGrow;
  361.         if(PtInRgn(hitPoint,getWindowCloseBoxRegion(window,tempRgn)))//in the Close Box?
  362.             return wInGoAway;
  363.         if(PtInRgn(hitPoint,getWindowZoomBoxRegion(window,tempRgn)))//in the Zoom Box?
  364.             return wInZoomOut;
  365.             
  366.         //Mac OS 8.0 or later
  367.         if(PtInRgn(hitPoint,getWindowCollapseBoxRegion(window,tempRgn)))//in the Collapse Box?
  368.             return wInCollapseBox;
  369.     }
  370.      //Mac OS 8.5 or later
  371.     if(PtInRgn(hitPoint,getWindowContentRegion(window,tempRgn))) //in window content region?
  372.         return wInContent;
  373.     if(PtInRgn(hitPoint,getWindowDragRegion(window,tempRgn)))//in window drag region?
  374.         return wInDrag;
  375.  
  376.     return wNoHit;//no significant area was hit.
  377. }
  378. SInt32 myWindowInitialize(WindowRef window,SInt32 param)
  379. {
  380.     /*------------------------------------------------------
  381.         perform any initialization for your window here
  382.     --------------------------------------------------------*/
  383.     return 0;
  384. }
  385. SInt32 myWindowCleanUp(WindowRef window,SInt32 param)
  386. {
  387.     /*------------------------------------------------------
  388.         dispose of anything allocated in Initialization
  389.     --------------------------------------------------------*/
  390.     return 0;
  391. }
  392. SInt32 myWindowDrawGrowBox(WindowRef window,SInt32 param)
  393. {
  394.     /*------------------------------------------------------
  395.         This function draws the grow box of the window
  396.     --------------------------------------------------------*/
  397.     RgnHandle growBoxRegion=NewRgn();
  398.     getWindowGrowBoxRegion(window,growBoxRegion);
  399.     //draw grow box here
  400.     return 0;
  401. }
  402.  
  403. SInt32 myWindowGetRegion(WindowRef window,SInt32 param)
  404. {
  405.     /*------------------------------------------------------
  406.         Define each of the window's regions
  407.     --------------------------------------------------------*/
  408.     GetWindowRegionPtr rgnRec=(GetWindowRegionPtr)param;
  409.  
  410.     switch(rgnRec->regionCode){
  411.         case kWindowTitleBarRgn:
  412.                                 getWindowTitleBarRegion(window,rgnRec->winRgn);
  413.                                 break;
  414.         case kWindowTitleTextRgn:
  415.                                 getWindowTitleTextRegion(window,rgnRec->winRgn);
  416.                                 break;
  417.         case kWindowCloseBoxRgn:
  418.                                 getWindowCloseBoxRegion(window,rgnRec->winRgn);
  419.                                 break;
  420.         case kWindowZoomBoxRgn:
  421.                                 getWindowZoomBoxRegion(window,rgnRec->winRgn);
  422.                                 break;
  423.         case kWindowDragRgn:
  424.                                 getWindowDragRegion(window,rgnRec->winRgn);
  425.                                 break;
  426.         case kWindowGrowRgn:
  427.                                 getWindowGrowBoxRegion(window,rgnRec->winRgn);
  428.                                 break;
  429.         case kWindowCollapseBoxRgn:
  430.                                 getWindowCollapseBoxRegion(window,rgnRec->winRgn);
  431.                                 break;
  432.         case kWindowStructureRgn:
  433.                                 getWindowStructureRegion(window,rgnRec->winRgn);
  434.                                 break;
  435.         case kWindowContentRgn:
  436.                                 getWindowContentRegion(window,rgnRec->winRgn);
  437.                                 break;
  438.         //Carbon Forward
  439.         case kWindowUpdateRgn:
  440.                                 getWindowUpdateRegion(window,rgnRec->winRgn);
  441.                                 break;
  442.         default:
  443.                 return errWindowRegionCodeInvalid;
  444.     }
  445.     return noErr;
  446. }
  447. SInt32 myWindowDragHilite(WindowRef window,SInt32 param)
  448. {
  449.     /*------------------------------------------------------
  450.         Hilight the window to show support for
  451.         drag-and-drop.
  452.     --------------------------------------------------------*/
  453.     if(param){
  454.         //hilite window
  455.     }else{
  456.         //unhilight window
  457.     }
  458.     return 0;
  459. }
  460. SInt32 myWindowModified(WindowRef window,SInt32 param)
  461. {
  462.     /*------------------------------------------------------
  463.         Called when a document's "modified" bit is changed
  464.     --------------------------------------------------------*/
  465.     if(param){
  466.         //document has been modified
  467.     }else{
  468.         //document has been saved
  469.     }
  470.     return 0;
  471. }
  472. SInt32 myWindowDrawInCurrentPort(WindowRef window,SInt32 param)
  473. {
  474.      /*------------------------------------------------------
  475.         same as myWindowDraw but must draw in current port.
  476.         myWindowDraw is defined to draw in the current port
  477.         so just call it directly.
  478.     --------------------------------------------------------*/
  479.     myWindowDraw(window,param);
  480.     return 0;
  481. }
  482. SInt32 myWindowStateChanged(WindowRef window,SInt32 param)
  483. {
  484.     /*------------------------------------------------------
  485.         use this method if you need notification of a state 
  486.         change after the internal data has been altered but
  487.         before the window is updated on the screen
  488.     --------------------------------------------------------*/
  489.     if(param & kWindowStateTitleChanged){
  490.         //the Title Has changed
  491.     }
  492.     if(param & kWindowStateSizeChanged){
  493.         //the window size has changed
  494.     }
  495.     if(param & kWindowStatePositionChanged){
  496.         //the window position has changed
  497.     }
  498.     if(param & kWindowStateZOrderChanged){
  499.         //the widow has changed Z order
  500.     }
  501.     if(param & kWindowStateVisibilityChanged){
  502.         //the window has been shown or hidden
  503.     }
  504.     if(param & kWindowStateHiliteChanged){
  505.         //the window has been selected or deselected
  506.     }
  507.     if(param & kWindowStateCollapseChanged){
  508.         //the window has been collapsed or expanded
  509.     }
  510.     return 0;
  511. }
  512. SInt32 myWindowDrawGrowOutline(WindowRef window,SInt32 Param)
  513. {
  514.     /*------------------------------------------------------
  515.         Draw the window's grow outline
  516.     --------------------------------------------------------*/
  517.     return 0;
  518. }
  519. SInt32 myWindowGetGrowImageRegion(WindowRef window,SInt32 param)
  520. {
  521.     /*------------------------------------------------------
  522.         Get region to xor during grow/resize.
  523.     --------------------------------------------------------*/
  524.     GetGrowImageRegionRec* rgnRec=(GetGrowImageRegionRec*)param;
  525.     #pragma unused(rgnRec)
  526.     
  527.     return noErr;
  528. }
  529.  
  530. void getCurrentPortBounds(Rect* inRect)
  531. {
  532.     /*------------------------------------------------------
  533.         Simple utility function to get the bounds of the
  534.         current port.
  535.     --------------------------------------------------------*/
  536.     CGrafPtr thePort;
  537.     GetPort(&thePort);
  538.     GetPortBounds(thePort,inRect);
  539. }