home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 2000 November: Tool Chest / Dev.CD Nov 00 TC Disk 1.toast / Sample Code / Graphics 2D / OffScreenControlUpdate / OffScreenControlUpdate.c < prev    next >
Encoding:
C/C++ Source or Header  |  2000-09-28  |  7.2 KB  |  259 lines  |  [TEXT/CWIE]

  1. /*
  2.     File:        OffScreenControlUpdate.c
  3.  
  4.     Contains:    A simple code sample which demonstrates how to draw controls into an off-screen
  5.                 GWorld so you can draw them back to the screen without flicker. 
  6.  
  7.     Written by:     
  8.  
  9.     Copyright:    Copyright © 1999 by Apple Computer, Inc., All Rights Reserved.
  10.  
  11.                 You may incorporate this Apple sample source code into your program(s) without
  12.                 restriction. This Apple sample source code has been provided "AS IS" and the
  13.                 responsibility for its operation is yours. You are not permitted to redistribute
  14.                 this Apple sample source code as "Apple sample source code" after having made
  15.                 changes. If you're going to re-distribute the source, we require that you make
  16.                 it clear in the source that the code was descended from Apple sample source
  17.                 code, but that you've made changes.
  18.  
  19.     Change History (most recent first):
  20.                 7/12/1999    Karl Groethe    Updated for Metrowerks Codewarror Pro 2.1
  21.                 
  22.  
  23. */
  24.  
  25. #define OLDROUTINELOCATIONS        0
  26. #define OLDROUTINENAMES            0
  27. #define SystemSevenOrLater        1
  28. #include <Sound.h>
  29. #ifndef __FONTS__
  30. #    include <Fonts.h>
  31. #endif
  32.  
  33. #ifndef __DIALOGS__
  34. #    include <Dialogs.h>
  35. #endif
  36.  
  37. #ifndef __QDOFFSCREEN__
  38. #    include <QDOffscreen.h>
  39. #endif
  40.  
  41. enum
  42. {
  43.     kDialogItemIndex_DrawButton = 3,
  44.     kDialogItemIndex_CheckBox
  45. };
  46.  
  47. static pascal OSErr InitMac (void)
  48. {
  49.     MaxApplZone ( );
  50.     InitGraf (&(qd.thePort));
  51.     InitFonts ( );
  52.     InitWindows ( );
  53.     InitMenus ( );
  54.     TEInit ( );
  55.     InitDialogs (nil);
  56.  
  57.     return noErr;
  58. }
  59.  
  60. static pascal GDHandle GetMaxControlDevice (ControlRef controlRef)
  61. {
  62.     GrafPtr        savePort            = qd.thePort;
  63.     Rect        globalControlRect    = (**controlRef).contrlRect;
  64.  
  65.     SetPort ((**controlRef).contrlOwner);
  66.     {
  67.         LocalToGlobal ((Point *) &(globalControlRect.top));
  68.         LocalToGlobal ((Point *) &(globalControlRect.bottom));
  69.     }
  70.     SetPort (savePort);
  71.  
  72.     return GetMaxDevice (&globalControlRect);
  73. }
  74.  
  75. static pascal OSErr BuggyDraw1ControlWithOffScreen (ControlRef controlRef, short transferMode)
  76. {
  77.     //
  78.     //    This doesn't work. Check boxes draw as push buttons. I suspect this
  79.     //    is because controls assume they live in a window, and for the
  80.     //    duration of the Draw1Control call in this function, the control
  81.     //    lives in a GWorld, not a window. Probably the CDEF dereferences
  82.     //    some offset beyond the end of the GWorld, since a window record
  83.     //    is bigger.
  84.     //
  85.  
  86.     OSErr err = noErr;
  87.  
  88.     GDHandle maxDevice = GetMaxControlDevice (controlRef);
  89.  
  90.     if (maxDevice)
  91.     {
  92.         GWorldPtr        grafWorld        = nil;
  93.         Rect            contrlRect        = (**controlRef).contrlRect;
  94.         PixMapHandle    contrlPixMapH    = (**maxDevice).gdPMap;
  95.         short            pixelDepth        = (**contrlPixMapH).pixelSize;
  96.         CTabHandle        cTable            = (**contrlPixMapH).pmTable;
  97.  
  98.         if (!(err = NewGWorld (&grafWorld,pixelDepth,&contrlRect,cTable,maxDevice,noNewDevice)))
  99.         {
  100.             GWorldPtr        saveGrafWorld    = nil;
  101.             GDHandle        saveGDH            = nil;
  102.             PixMapHandle    pixMapH            = GetGWorldPixMap (grafWorld);
  103.  
  104.             GetGWorld (&saveGrafWorld,&saveGDH);
  105.             SetGWorld (grafWorld,nil);
  106.  
  107.             if (LockPixels (pixMapH)) // this should always work, but be paranoid
  108.             {
  109.                 GrafPtr        contrlOwner        = (**controlRef).contrlOwner;
  110.                 BitMapPtr    srcBitMap        = &(((GrafPtr) grafWorld)->portBits),
  111.                             destBitMap        = &(contrlOwner->portBits);
  112.  
  113.                 EraseRect (&contrlRect);
  114.                 (**controlRef).contrlOwner = (GrafPtr) grafWorld;
  115.                 Draw1Control (controlRef);
  116.                 (**controlRef).contrlOwner = contrlOwner;
  117.  
  118.                 CopyBits (srcBitMap,destBitMap,&contrlRect,&contrlRect,transferMode,nil);
  119.  
  120.                 UnlockPixels (pixMapH);
  121.             }
  122.  
  123.             SetGWorld (saveGrafWorld,saveGDH);
  124.             DisposeGWorld (grafWorld);
  125.         }
  126.     }
  127.  
  128.     return err;
  129. }
  130.  
  131. static pascal Boolean GrafPortIsColor (GrafPtr gp)
  132. {
  133.     if (!gp) gp = qd.thePort;
  134.     return (0xC000 & (((CGrafPtr) gp)->portVersion)) ? true : false;
  135. }
  136.  
  137. static pascal OSErr Draw1ControlWithOffScreen (ControlRef controlRef)
  138. {
  139.     //
  140.     //    [1]        create a GWorld with the same coords as the control
  141.     //            and as deep as the deepest intersecting monitor
  142.     //    [2]        make sure nothing gets colorized by CopyBits
  143.     //    [3]        grab the screen pixels that will be under the control
  144.     //    [4]        make the control's GrafPort have the GWorld's pixels
  145.     //    [5]        draw the control into the off-screen bits
  146.     //    [6]        blast the control image onto the screen
  147.     //
  148.  
  149.     OSErr err = noErr;
  150.  
  151.     GrafPtr contrlOwner = (**controlRef).contrlOwner;
  152.  
  153.     if (!GrafPortIsColor (contrlOwner))
  154.         err = paramErr;
  155.         //    contrlOwner must be color because the GWorld must be color
  156.         //    and both ports must be the same
  157.     else
  158.     {
  159.         // begin 1
  160.  
  161.         GDHandle maxDevice = GetMaxControlDevice (controlRef);
  162.  
  163.         if (!maxDevice)
  164.             err = nilHandleErr;
  165.         else
  166.         {
  167.             Rect            contrlRect    = (**controlRef).contrlRect;
  168.             GWorldPtr        grafWorld    = nil;
  169.             PixMapHandle    gdPMap        = (**maxDevice).gdPMap;
  170.             short            pixelSize    = (**gdPMap).pixelSize;
  171.             CTabHandle        pmTable        = (**gdPMap).pmTable;
  172.  
  173.             if (!(err = NewGWorld (&grafWorld,pixelSize,&contrlRect,pmTable,maxDevice,0)))
  174.             {
  175.                 PixMapHandle grafWorldPixMapH = GetGWorldPixMap (grafWorld);
  176.  
  177.                 if (!grafWorldPixMapH)
  178.                     err = nilHandleErr;
  179.                 else if (!LockPixels (grafWorldPixMapH))
  180.                     err = updPixMemErr;
  181.                 else
  182.                 {
  183.                     // end 1
  184.  
  185.                     BitMapPtr    grafWorldBitMap        = &(((GrafPtr) grafWorld)->portBits),            // 3,4,6
  186.                                 controlBitMap        = &(contrlOwner->portBits);                        // 3,4,6
  187.                     BitMap        saveControlBitMap    = *controlBitMap;                                // 4
  188.                     RGBColor    rgbFgColor            = grafWorld->rgbFgColor,                        // 2
  189.                                 rgbBkColor            = grafWorld->rgbBkColor;                        // 2
  190.                     GWorldPtr    saveGrafWorld        = nil;                                            // 2
  191.                     GDHandle    saveGDH                = nil;                                            // 2
  192.  
  193.                     GetGWorld (&saveGrafWorld,&saveGDH);                                            // 2
  194.  
  195.                     SetGWorld (grafWorld,nil);                                                        // 2
  196.                     ForeColor (blackColor);                                                            // 2
  197.                     BackColor (whiteColor);                                                            // 2
  198.                     CopyBits (controlBitMap,grafWorldBitMap,&contrlRect,&contrlRect,srcCopy,nil);    // 3
  199.                     RGBForeColor (&rgbFgColor);                                                        // 2
  200.                     RGBBackColor (&rgbBkColor);                                                        // 2
  201.  
  202.                     *controlBitMap = *grafWorldBitMap;                                                // 4
  203.                     PortChanged (contrlOwner);                                                        // 4
  204.                     Draw1Control (controlRef);                                                        // 5
  205.                     *controlBitMap = saveControlBitMap;                                                // 4
  206.                     PortChanged (contrlOwner);                                                        // 4
  207.  
  208.                     SetGWorld ((CGrafPtr)contrlOwner,nil);                                            // 2
  209.                     rgbFgColor = ((CGrafPtr)contrlOwner)->rgbFgColor,                                // 2
  210.                     rgbBkColor = ((CGrafPtr)contrlOwner)->rgbBkColor;                                // 2
  211.                     ForeColor (blackColor);                                                            // 2
  212.                     BackColor (whiteColor);                                                            // 2
  213.                     CopyBits (grafWorldBitMap,controlBitMap,&contrlRect,&contrlRect,srcCopy,nil);    // 6
  214.                     RGBForeColor (&rgbFgColor);                                                        // 2
  215.                     RGBBackColor (&rgbBkColor);                                                        // 2
  216.  
  217.                     SetGWorld (saveGrafWorld,saveGDH);                                                // 2
  218.                     UnlockPixels (grafWorldPixMapH);                                                // 1
  219.                 }
  220.                 DisposeGWorld (grafWorld);                                                            // 1
  221.             }
  222.         }
  223.     }
  224.  
  225.     return err;
  226. }
  227.  
  228. void main (void)
  229. {
  230.     if (InitMac ( ))
  231.         SysBeep (10);
  232.     else
  233.     {
  234.         DialogRef dlgRef = GetNewDialog (129,nil,(WindowRef)-1);
  235.         if (dlgRef)
  236.         {
  237.             short itemHit;
  238.  
  239.             SetDialogDefaultItem (dlgRef,kStdOkItemIndex);
  240.  
  241.             do
  242.             {
  243.                 ModalDialog (nil,&itemHit);
  244.  
  245.                 if (itemHit == kDialogItemIndex_DrawButton)
  246.                 {
  247.                     short iType; Handle iHandle; Rect iRect;
  248.                     GetDialogItem (dlgRef,kDialogItemIndex_CheckBox,&iType,&iHandle,&iRect);
  249.                     if (Draw1ControlWithOffScreen ((ControlRef)iHandle))
  250.                         SysBeep (10);
  251.                 }
  252.             }
  253.             while (itemHit != kStdOkItemIndex);
  254.  
  255.             DisposeDialog (dlgRef);
  256.         }
  257.     }
  258. }
  259.