Retired Document
Important: This sample code may not represent best practices for current development. The project may use deprecated symbols and illustrate technologies and techniques that are no longer recommended.
OffScreenControlUpdate.c
/* |
File: OffScreenControlUpdate.c |
Contains: A simple code sample which demonstrates how to draw controls into an off-screen |
GWorld so you can draw them back to the screen without flicker. |
Written by: |
Copyright: Copyright © 1999 by Apple Computer, Inc., All Rights Reserved. |
You may incorporate this Apple sample source code into your program(s) without |
restriction. This Apple sample source code has been provided "AS IS" and the |
responsibility for its operation is yours. You are not permitted to redistribute |
this Apple sample source code as "Apple sample source code" after having made |
changes. If you're going to re-distribute the source, we require that you make |
it clear in the source that the code was descended from Apple sample source |
code, but that you've made changes. |
Change History (most recent first): |
7/12/1999 Karl Groethe Updated for Metrowerks Codewarror Pro 2.1 |
*/ |
#define OLDROUTINELOCATIONS 0 |
#define OLDROUTINENAMES 0 |
#define SystemSevenOrLater 1 |
#include <Sound.h> |
#ifndef __FONTS__ |
# include <Fonts.h> |
#endif |
#ifndef __DIALOGS__ |
# include <Dialogs.h> |
#endif |
#ifndef __QDOFFSCREEN__ |
# include <QDOffscreen.h> |
#endif |
enum |
{ |
kDialogItemIndex_DrawButton = 3, |
kDialogItemIndex_CheckBox |
}; |
static pascal OSErr InitMac (void) |
{ |
MaxApplZone ( ); |
InitGraf (&(qd.thePort)); |
InitFonts ( ); |
InitWindows ( ); |
InitMenus ( ); |
TEInit ( ); |
InitDialogs (nil); |
return noErr; |
} |
static pascal GDHandle GetMaxControlDevice (ControlRef controlRef) |
{ |
GrafPtr savePort = qd.thePort; |
Rect globalControlRect = (**controlRef).contrlRect; |
SetPort ((**controlRef).contrlOwner); |
{ |
LocalToGlobal ((Point *) &(globalControlRect.top)); |
LocalToGlobal ((Point *) &(globalControlRect.bottom)); |
} |
SetPort (savePort); |
return GetMaxDevice (&globalControlRect); |
} |
static pascal OSErr BuggyDraw1ControlWithOffScreen (ControlRef controlRef, short transferMode) |
{ |
// |
// This doesn't work. Check boxes draw as push buttons. I suspect this |
// is because controls assume they live in a window, and for the |
// duration of the Draw1Control call in this function, the control |
// lives in a GWorld, not a window. Probably the CDEF dereferences |
// some offset beyond the end of the GWorld, since a window record |
// is bigger. |
// |
OSErr err = noErr; |
GDHandle maxDevice = GetMaxControlDevice (controlRef); |
if (maxDevice) |
{ |
GWorldPtr grafWorld = nil; |
Rect contrlRect = (**controlRef).contrlRect; |
PixMapHandle contrlPixMapH = (**maxDevice).gdPMap; |
short pixelDepth = (**contrlPixMapH).pixelSize; |
CTabHandle cTable = (**contrlPixMapH).pmTable; |
if (!(err = NewGWorld (&grafWorld,pixelDepth,&contrlRect,cTable,maxDevice,noNewDevice))) |
{ |
GWorldPtr saveGrafWorld = nil; |
GDHandle saveGDH = nil; |
PixMapHandle pixMapH = GetGWorldPixMap (grafWorld); |
GetGWorld (&saveGrafWorld,&saveGDH); |
SetGWorld (grafWorld,nil); |
if (LockPixels (pixMapH)) // this should always work, but be paranoid |
{ |
GrafPtr contrlOwner = (**controlRef).contrlOwner; |
BitMapPtr srcBitMap = &(((GrafPtr) grafWorld)->portBits), |
destBitMap = &(contrlOwner->portBits); |
EraseRect (&contrlRect); |
(**controlRef).contrlOwner = (GrafPtr) grafWorld; |
Draw1Control (controlRef); |
(**controlRef).contrlOwner = contrlOwner; |
CopyBits (srcBitMap,destBitMap,&contrlRect,&contrlRect,transferMode,nil); |
UnlockPixels (pixMapH); |
} |
SetGWorld (saveGrafWorld,saveGDH); |
DisposeGWorld (grafWorld); |
} |
} |
return err; |
} |
static pascal Boolean GrafPortIsColor (GrafPtr gp) |
{ |
if (!gp) gp = qd.thePort; |
return (0xC000 & (((CGrafPtr) gp)->portVersion)) ? true : false; |
} |
static pascal OSErr Draw1ControlWithOffScreen (ControlRef controlRef) |
{ |
// |
// [1] create a GWorld with the same coords as the control |
// and as deep as the deepest intersecting monitor |
// [2] make sure nothing gets colorized by CopyBits |
// [3] grab the screen pixels that will be under the control |
// [4] make the control's GrafPort have the GWorld's pixels |
// [5] draw the control into the off-screen bits |
// [6] blast the control image onto the screen |
// |
OSErr err = noErr; |
GrafPtr contrlOwner = (**controlRef).contrlOwner; |
if (!GrafPortIsColor (contrlOwner)) |
err = paramErr; |
// contrlOwner must be color because the GWorld must be color |
// and both ports must be the same |
else |
{ |
// begin 1 |
GDHandle maxDevice = GetMaxControlDevice (controlRef); |
if (!maxDevice) |
err = nilHandleErr; |
else |
{ |
Rect contrlRect = (**controlRef).contrlRect; |
GWorldPtr grafWorld = nil; |
PixMapHandle gdPMap = (**maxDevice).gdPMap; |
short pixelSize = (**gdPMap).pixelSize; |
CTabHandle pmTable = (**gdPMap).pmTable; |
if (!(err = NewGWorld (&grafWorld,pixelSize,&contrlRect,pmTable,maxDevice,0))) |
{ |
PixMapHandle grafWorldPixMapH = GetGWorldPixMap (grafWorld); |
if (!grafWorldPixMapH) |
err = nilHandleErr; |
else if (!LockPixels (grafWorldPixMapH)) |
err = updPixMemErr; |
else |
{ |
// end 1 |
BitMapPtr grafWorldBitMap = &(((GrafPtr) grafWorld)->portBits), // 3,4,6 |
controlBitMap = &(contrlOwner->portBits); // 3,4,6 |
BitMap saveControlBitMap = *controlBitMap; // 4 |
RGBColor rgbFgColor = grafWorld->rgbFgColor, // 2 |
rgbBkColor = grafWorld->rgbBkColor; // 2 |
GWorldPtr saveGrafWorld = nil; // 2 |
GDHandle saveGDH = nil; // 2 |
GetGWorld (&saveGrafWorld,&saveGDH); // 2 |
SetGWorld (grafWorld,nil); // 2 |
ForeColor (blackColor); // 2 |
BackColor (whiteColor); // 2 |
CopyBits (controlBitMap,grafWorldBitMap,&contrlRect,&contrlRect,srcCopy,nil); // 3 |
RGBForeColor (&rgbFgColor); // 2 |
RGBBackColor (&rgbBkColor); // 2 |
*controlBitMap = *grafWorldBitMap; // 4 |
PortChanged (contrlOwner); // 4 |
Draw1Control (controlRef); // 5 |
*controlBitMap = saveControlBitMap; // 4 |
PortChanged (contrlOwner); // 4 |
SetGWorld ((CGrafPtr)contrlOwner,nil); // 2 |
rgbFgColor = ((CGrafPtr)contrlOwner)->rgbFgColor, // 2 |
rgbBkColor = ((CGrafPtr)contrlOwner)->rgbBkColor; // 2 |
ForeColor (blackColor); // 2 |
BackColor (whiteColor); // 2 |
CopyBits (grafWorldBitMap,controlBitMap,&contrlRect,&contrlRect,srcCopy,nil); // 6 |
RGBForeColor (&rgbFgColor); // 2 |
RGBBackColor (&rgbBkColor); // 2 |
SetGWorld (saveGrafWorld,saveGDH); // 2 |
UnlockPixels (grafWorldPixMapH); // 1 |
} |
DisposeGWorld (grafWorld); // 1 |
} |
} |
} |
return err; |
} |
void main (void) |
{ |
if (InitMac ( )) |
SysBeep (10); |
else |
{ |
DialogRef dlgRef = GetNewDialog (129,nil,(WindowRef)-1); |
if (dlgRef) |
{ |
short itemHit; |
SetDialogDefaultItem (dlgRef,kStdOkItemIndex); |
do |
{ |
ModalDialog (nil,&itemHit); |
if (itemHit == kDialogItemIndex_DrawButton) |
{ |
short iType; Handle iHandle; Rect iRect; |
GetDialogItem (dlgRef,kDialogItemIndex_CheckBox,&iType,&iHandle,&iRect); |
if (Draw1ControlWithOffScreen ((ControlRef)iHandle)) |
SysBeep (10); |
} |
} |
while (itemHit != kStdOkItemIndex); |
DisposeDialog (dlgRef); |
} |
} |
} |
Copyright © 2003 Apple Computer, Inc. All Rights Reserved. Terms of Use | Privacy Policy | Updated: 2003-07-22