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.
Windows.c
/* |
File: Windows.c |
Contains: Handle application's windows |
Written by: Chris White |
Copyright: Copyright © 1996-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): |
8/6/1999 Karl Groethe Updated for Metrowerks Codewarror Pro 2.1 |
*/ |
#pragma segment Core |
#include <Sound.h> |
// System Includes |
#ifndef __TYPES__ |
#include <Types.h> |
#endif |
#ifndef __WINDOWS__ |
#include <Windows.h> |
#endif |
#ifndef __DIALOGS__ |
#include <Dialogs.h> |
#endif |
#ifndef __QUICKDRAW__ |
#include <Quickdraw.h> |
#endif |
#ifndef __PICTUTILS__ |
#include <PictUtils.h> |
#endif |
#ifndef __RESOURCES__ |
#include <Resources.h> |
#endif |
#ifndef __FONTS__ |
#include <Fonts.h> |
#endif |
#ifndef __TOOLUTILS__ |
#include <ToolUtils.h> |
#endif |
#ifndef __ERRORS__ |
#include <Errors.h> |
#endif |
// Application Includes |
#ifndef __BAREBONES__ |
#include "BareBones.h" |
#endif |
#ifndef __PROTOTYPES__ |
#include "Prototypes.h" |
#endif |
// Static prototypes |
static OSErr CreateDocumentWindow ( WindowRef* windowRef ); |
static GWorldPtr CreateOffscreen ( CTabHandle theCTabHndl, SInt16 theXsize, SInt16 theYsize, |
SInt16 theBitDepth, GWorldFlags theFlags ); |
static OSErr DrawPictToOffscreen ( PicHandle thePictHndl, GWorldPtr theOffscreen ); |
static OSErr DrawOffscreenToWindow ( GWorldPtr theOffscreen, WindowPtr theWindow ); |
static Rect GetWindowVisibleRect ( WindowRef theWindow, SInt16 theSizeX, SInt16 theSizeY ); |
static void SaveSetMMUMode ( Boolean bIsSaveMode ); |
static void DrawClippedScrollBarLines ( WindowRef theWindow ); |
static void DrawClippedGrowIcon ( WindowRef theWindow ); |
static void HandleContentClick ( WindowRef theWindow, EventRecord* event ); |
static OSErr CreateWindowInfo ( WindowRef windowRef, Size infoSize ); |
static pascal OSErr SafeGetPictInfo ( PicHandle thePictHandle, PictInfo* thePictInfo, |
SInt16 verb, SInt16 colorsRequested, |
SInt16 colorPickMethod, SInt16 version ); |
static void SizeScrollBars ( WindowRef theWindow ); |
static Point GetMaximumWindowSize ( WindowRef theWindow ); |
// Default RGB Colors |
static const RGBColor kRGBBlack = {0x0000, 0x0000, 0x0000}; |
static const RGBColor kRGBWhite = {0xFFFF, 0xFFFF, 0xFFFF}; |
// |
// This is called to create the application's window. |
// |
void CreateWindow ( void ) |
{ |
OSErr theErr; |
WindowRef theWindow; |
theErr = CreateDocumentWindow ( &theWindow ); |
if ( theErr ) |
AlertUser ( kGenericErrorStr, theErr, "\p" ); |
return; |
} |
// |
// This will close the application's window, dispose of any storage we've hung |
// off the window, and then dispose of the window itself. |
// |
WindowRef DestroyWindow ( WindowRef windowRef ) |
{ |
if ( windowRef ) |
{ |
tWindowInfoPtr theInfo; |
theInfo = (tWindowInfoPtr) GetWRefCon ( windowRef ); |
if ( theInfo ) |
{ |
if ( theInfo->hScrollBar ) |
DisposeControl ( theInfo->hScrollBar ); |
if ( theInfo->vScrollBar ) |
DisposeControl ( theInfo->vScrollBar ); |
if ( theInfo->offscreen ) |
DisposeGWorld ( theInfo->offscreen ); |
DisposePtr ( (Ptr) theInfo ); |
} |
DisposeWindow ( windowRef ); |
} |
return nil; |
} |
void DoActivate ( EventRecord* theEvent ) |
{ |
Boolean bActiveFlag = theEvent->modifiers & resumeFlag; |
WindowRef theWindow = (WindowRef) theEvent->message; |
GrafPtr savePort; |
tWindowInfoPtr theInfo; |
gInBackground = (theEvent->modifiers & resumeFlag) == 0; |
GetPort ( &savePort ); |
SetPortWindowPort ( theWindow ); |
theInfo = (tWindowInfoPtr) GetWRefCon ( theWindow ); |
if ( bActiveFlag ) |
{ |
ShowControl ( theInfo->hScrollBar ); |
ShowControl ( theInfo->vScrollBar ); |
} |
else |
{ |
HideControl ( theInfo->hScrollBar ); |
HideControl ( theInfo->vScrollBar ); |
DrawClippedScrollBarLines ( theWindow ); |
} |
DrawClippedGrowIcon ( theWindow ); |
SetPort ( savePort ); |
return; |
} |
void DoUpdate ( WindowRef theWindow ) |
{ |
GrafPtr savePort; |
CGrafPtr thePort; |
thePort = GetWindowPort ( theWindow ); |
GetPort ( &savePort ); |
SetPortWindowPort ( theWindow ); |
BeginUpdate ( theWindow ); // visRgn temporarily = updateRgn |
EraseRect ( &thePort->portRect ); |
UpdateWindowContent ( theWindow ); |
if ( gInBackground ) |
DrawClippedScrollBarLines ( theWindow ); |
else |
UpdateControls ( theWindow, theWindow->visRgn ); |
DrawClippedGrowIcon ( theWindow ); |
EndUpdate ( theWindow ); // restore normal visRgn of grafport |
SetPort ( savePort ); |
return; |
} |
void UpdateWindowContent ( WindowRef theWindow ) |
{ |
tWindowInfoPtr theInfo; |
theInfo = (tWindowInfoPtr) GetWRefCon ( theWindow ); |
DrawOffscreenToWindow ( theInfo->offscreen, theWindow ); |
return; |
} |
void DoContentClick ( WindowRef theWindow, EventRecord* theEvent ) |
{ |
OSErr theErr = noErr; |
WindowRef frontWindow; |
// If a movable modal is active, ignore click in an inactive |
// window, otherwise select it or handle the content click. |
frontWindow = FrontWindow ( ); |
if ( theWindow != frontWindow ) |
{ |
if ( IsMovableModal ( frontWindow ) ) |
SysBeep ( 30 ); |
else |
SelectWindow ( theWindow ); |
} |
else |
{ |
SInt16 thePart; |
GrafPtr savePort; |
ControlRef theControl; |
Point localPt; |
localPt = theEvent->where; |
GlobalToLocal ( &localPt ); |
thePart = FindControl ( localPt, theWindow, &theControl ); |
GetPort ( &savePort ); |
SetPortWindowPort ( theWindow ); |
if ( thePart ) |
{ |
switch ( thePart ) |
{ |
case kControlUpButtonPart: |
case kControlDownButtonPart: |
case kControlPageUpPart: |
case kControlPageDownPart: |
TrackControl ( theControl, localPt, gScrollControlActionUPP ); |
break; |
case kControlIndicatorPart: |
if ( BeginThumbTracking ( theControl ) == noErr ) |
{ |
TrackControl ( theControl, localPt, |
(ControlActionUPP) gScrollThumbActionUPP ); |
EndThumbTracking ( ); |
} |
break; |
} |
} |
else |
HandleContentClick ( theWindow, theEvent ); |
SetPort ( savePort ); |
} |
return; |
} // DoContentClick |
void DoGrowWindow ( WindowRef theWindow, EventRecord* theEvent ) |
{ |
WindowPtr savePort; |
SInt32 returnCoord; |
Rect resizeBounds; |
SInt16 theWidth, |
theHeight; |
Point theMaxSize; |
GetPort ( &savePort ); |
theMaxSize = GetMaximumWindowSize ( theWindow ); |
SetRect ( &resizeBounds, 96, 96, theMaxSize.h, theMaxSize.v ); |
returnCoord = GrowWindow ( theWindow, theEvent->where, &resizeBounds ); |
theHeight = HiWord ( returnCoord ); |
theWidth = LoWord ( returnCoord ); |
SizeWindow ( theWindow, theWidth, theHeight, true ); |
SizeScrollBars ( theWindow ); |
SetPort ( theWindow ); |
InvalRect ( &theWindow->portRect ); |
SetPort ( savePort ); |
return; |
} |
void DoDragWindow ( WindowRef theWindow, EventRecord* theEvent ) |
{ |
WindowRef frontWindow; |
// If a movable modal is active, ignore click in an inactive |
// title bar, otherwise let the Window Manager handle it. |
frontWindow = FrontWindow ( ); |
if ( theWindow != frontWindow && IsMovableModal ( frontWindow ) ) |
SysBeep ( 30 ); |
else |
{ |
RgnHandle theRgn; |
Rect dragRect; |
theRgn = GetGrayRgn ( ); |
dragRect = (*theRgn)->rgnBBox; |
DragWindow ( theWindow, theEvent->where, &dragRect ); |
} |
return; |
} |
OSErr DoAboutBox ( void ) |
{ |
OSErr theErr = noErr; |
SInt16 theItem = 0; |
GrafPtr savePort = nil; |
DialogRef theDialog; |
ModalFilterUPP theFilter = nil; |
theDialog = GetNewDialog ( kAboutDialog, nil, (WindowPtr) -1 ); |
GetPort ( &savePort ); |
SetPort ( theDialog ); |
ShowWindow ( theDialog ); |
// Get the standard filter proc |
theErr = GetStdFilterProc ( &theFilter ); |
if ( theErr ) |
goto CleanupAndBail; |
// Tell the dialog manager to use the default button |
SetDialogDefaultItem ( theDialog, kStdOkItemIndex ); |
// Modal dialog loop |
do |
{ |
// Use "theFilter" in ModalDialog call |
ModalDialog ( theFilter, &theItem ); |
} while ( theItem != kStdOkItemIndex ); |
CleanupAndBail: |
DisposeDialog ( theDialog ); |
SetPort ( savePort ); |
return theErr; |
} |
// |
// Creates a document window containing a picture. |
// |
static OSErr CreateDocumentWindow ( WindowRef* windowRef ) |
{ |
OSErr theErr = noErr; |
WindowRef theWindow; |
Point theImageSize; |
PicHandle thePict = nil; |
PictInfo thePictInfo; |
tWindowInfoPtr theInfo; |
theWindow = GetNewCWindow ( kDisplayWindow, nil, (WindowRef) -1 ); |
if ( theWindow == nil ) |
return (ResError ( )) ? ResError ( ) : resNotFound; |
theErr = CreateWindowInfo ( theWindow, sizeof ( tWindowInfo ) ); |
if ( theErr ) goto CleanupAndBail; |
theInfo = (tWindowInfoPtr) GetWRefCon ( theWindow ); |
SetPortWindowPort ( theWindow ); |
thePict = GetPicture ( kPictureID ); |
if ( thePict == nil ) goto CleanupAndBail; |
theErr = SafeGetPictInfo ( thePict, &thePictInfo, returnColorTable, 256, systemMethod, 0 ); |
if ( theErr ) goto CleanupAndBail; |
theImageSize.h = thePictInfo.sourceRect.right - thePictInfo.sourceRect.left; |
theImageSize.v = thePictInfo.sourceRect.bottom - thePictInfo.sourceRect.top; |
theInfo->offscreen = CreateOffscreen ( (thePictInfo.depth <= 8) ? thePictInfo.theColorTable : nil, |
theImageSize.h, theImageSize.v, thePictInfo.depth, |
kNoFlags ); |
if ( theInfo->offscreen == nil ) goto CleanupAndBail; |
theInfo->hScrollBar = GetNewControl ( kScrollBar, theWindow ); |
theInfo->vScrollBar = GetNewControl ( kScrollBar, theWindow ); |
if ( theInfo->hScrollBar == nil || theInfo->vScrollBar == nil) |
goto CleanupAndBail; |
// Setup the correct control values |
SetControlMinimum ( theInfo->hScrollBar, 0 ); |
SetControlMinimum ( theInfo->vScrollBar, 0 ); |
SetControlValue ( theInfo->hScrollBar, 0 ); |
SetControlValue ( theInfo->vScrollBar, 0 ); |
SizeScrollBars ( theWindow ); |
theErr = DrawPictToOffscreen ( thePict, theInfo->offscreen ); |
if ( theErr ) goto CleanupAndBail; |
SelectWindow ( theWindow ); |
ShowWindow ( theWindow ); |
*windowRef = theWindow; |
if ( thePict ) |
ReleaseResource ( (Handle) thePict ); |
return noErr; |
CleanupAndBail: |
// Don't forget to free any storage we've used so far |
if ( thePict ) |
ReleaseResource ( (Handle) thePict ); |
DestroyWindow ( theWindow ); |
return theErr; |
} |
static GWorldPtr CreateOffscreen ( CTabHandle theCTabHndl, SInt16 theXsize, SInt16 theYsize, |
SInt16 theBitDepth, GWorldFlags theFlags ) |
{ |
GWorldPtr theGWorld = nil; |
QDErr theErr; |
Rect theRect; |
SetRect ( &theRect, 0, 0, theXsize, theYsize ); |
theErr = NewGWorld ( &theGWorld, theBitDepth, &theRect, theCTabHndl, nil, theFlags ); |
#if WARNINGS |
if ( theErr ) |
DebugStrNum ( "\p CreateOffscreen: ", theErr ); |
#endif |
return theGWorld; |
} |
static OSErr DrawPictToOffscreen ( PicHandle thePictHndl, GWorldPtr theOffscreen ) |
{ |
PixMapHandle theGWorldPMHndl; |
GDHandle saveGDevice; |
CGrafPtr saveGWorld; |
OSErr theErr = noErr; |
GetGWorld ( &saveGWorld, &saveGDevice ); |
SetGWorld ( theOffscreen, nil ); |
// We'll initialize out port settings here. |
// If you don't set the foreground and background colors to black |
// and white, colorisation can occur during the call to CopyBits. |
RGBForeColor ( &kRGBBlack ); |
RGBBackColor ( &kRGBWhite ); |
// Reset the transfer mode |
PenMode ( srcCopy ); |
theGWorldPMHndl = GetGWorldPixMap ( theOffscreen ); |
LockPixels ( theGWorldPMHndl ); |
EraseRect ( &theOffscreen->portRect ); |
// render the image into the offscreen buffer |
HLock ( (Handle) thePictHndl ); |
DrawPicture ( thePictHndl, &theOffscreen->portRect ); |
HUnlock ( (Handle) thePictHndl ); |
UnlockPixels ( theGWorldPMHndl ); |
SetGWorld ( saveGWorld, saveGDevice ); |
return theErr; |
} |
static OSErr DrawOffscreenToWindow ( GWorldPtr theOffscreen, WindowPtr theWindow ) |
{ |
OSErr theErr = noErr; |
CGrafPtr savePort = nil; |
GDHandle saveGDevice; |
PixMapHandle thePixMapHndl = nil; |
RGBColor saveForeColor, |
saveBackColor; |
Rect sourceRect, |
destRect; |
GetGWorld ( &savePort, &saveGDevice ); |
SetGWorld ( theOffscreen, nil ); |
GetForeColor ( &saveForeColor ); |
GetBackColor ( &saveBackColor ); |
RGBForeColor ( &kRGBBlack ); |
RGBBackColor ( &kRGBWhite ); |
thePixMapHndl = GetGWorldPixMap ( theOffscreen ); |
if ( PixMap32Bit ( thePixMapHndl ) ) // if 32bit mode needed == true |
SaveSetMMUMode ( true ); |
if ( !LockPixels ( thePixMapHndl ) ) |
goto CleanupAndBail; |
sourceRect = theOffscreen->portRect; |
destRect = theWindow->portRect; |
destRect.right -= kScrollBarWidth; // exclude scrollbar area |
destRect.bottom -= kScrollBarWidth; |
if ( !EqualRect ( &sourceRect, &destRect ) ) |
sourceRect = GetWindowVisibleRect ( theWindow, destRect.right, destRect.bottom ); |
SetGWorld ( savePort, saveGDevice ); |
savePort = nil; |
CopyBits ( (BitMap*) *thePixMapHndl, (BitMap*) &theWindow->portBits, |
&sourceRect, &destRect, srcCopy, nil); |
CleanupAndBail: |
if ( savePort ) |
SetGWorld ( savePort, saveGDevice ); |
RGBForeColor ( &saveForeColor ); |
RGBBackColor ( &saveBackColor ); |
UnlockPixels ( thePixMapHndl ); |
SaveSetMMUMode ( false ); |
return theErr; |
} |
static void DrawClippedScrollBarLines ( WindowRef theWindow ) |
{ |
CGrafPtr thePort; |
Rect theRect; |
thePort = GetWindowPort ( theWindow ); |
theRect = thePort->portRect; |
MoveTo ( theRect.left, theRect.bottom - kScrollBarWidthAdjust ); |
LineTo ( theRect.right - kScrollBarWidthAdjust, theRect.bottom - kScrollBarWidthAdjust ); |
MoveTo ( theRect.right - kScrollBarWidthAdjust, theRect.top ); |
LineTo ( theRect.right - kScrollBarWidthAdjust, theRect.bottom - kScrollBarWidthAdjust ); |
return; |
} |
static void DrawClippedGrowIcon ( WindowRef theWindow ) |
{ |
CGrafPtr thePort; |
RgnHandle saveClip = nil; |
Rect newClip; |
thePort = GetWindowPort ( theWindow ); |
saveClip = NewRgn ( ); |
GetClip ( saveClip ); |
newClip = thePort->portRect; |
newClip.top = newClip.bottom - kScrollBarWidth; |
newClip.left = newClip.right - kScrollBarWidth; |
ClipRect ( &newClip ); |
DrawGrowIcon ( theWindow ); |
SetClip ( saveClip ); |
DisposeRgn ( saveClip ); |
return; |
} |
static Rect GetWindowVisibleRect ( WindowRef theWindow, SInt16 theSizeX, SInt16 theSizeY ) |
{ |
Rect displayRect; |
SInt16 theValueX, |
theValueY; |
tWindowInfoPtr theInfo; |
theInfo = (tWindowInfoPtr) GetWRefCon ( theWindow ); |
theValueX = GetControlValue ( theInfo->hScrollBar ); |
theValueY = GetControlValue ( theInfo->vScrollBar ); |
SetRect ( &displayRect, theValueX, theValueY, theValueX + theSizeX, theValueY + theSizeY ); |
return displayRect; |
} |
static void SaveSetMMUMode ( Boolean bIsSaveMode ) |
{ |
static signed char theAddrMode = true32b; |
static Boolean bSwapModeNeeded = false; |
if ( bIsSaveMode ) |
{ |
if ( GetMMUMode ( ) == false32b ) // get current addr mode |
{ |
bSwapModeNeeded = true; // in 24 bit mode swap needed |
SwapMMUMode ( &theAddrMode ); // switch to 32 bit mode |
} |
} |
else if ( bSwapModeNeeded ) |
SwapMMUMode ( &theAddrMode ); |
return; |
} |
static void HandleContentClick ( WindowRef theWindow, EventRecord* event ) |
{ |
#pragma unused(theWindow) |
Point localPt; |
localPt = event->where; |
GlobalToLocal ( &localPt ); |
// Handle any content clicks here |
return; |
} |
// |
// Creates the storage for the data to hang off a window or dialog |
// |
static OSErr CreateWindowInfo ( WindowRef windowRef, Size infoSize ) |
{ |
OSErr theErr; |
Ptr theInfo = nil; |
theInfo = NewPtrClear ( infoSize ); |
theErr = MemError ( ); |
if ( theErr ) |
return theErr; |
SetWRefCon ( windowRef, (long) theInfo ); |
return noErr; |
} |
// |
// The GetPictInfo routine has a bug which will allow all hell to |
// break loose if there isn't enough temporary memory available. |
// |
static pascal OSErr SafeGetPictInfo ( PicHandle thePictHandle, PictInfo* thePictInfo, SInt16 verb, SInt16 colorsRequested, SInt16 colorPickMethod, SInt16 version ) |
{ |
const SInt32 kMinLowMem = 10240; // 10K isn't too much to ask for! |
if ( TempFreeMem ( ) < kMinLowMem ) |
return memFullErr; |
return GetPictInfo ( thePictHandle, thePictInfo, verb, colorsRequested, colorPickMethod, version ); |
} |
static void SizeScrollBars ( WindowRef theWindow ) |
{ |
SInt16 maxXsize, |
maxYsize; |
tWindowInfoPtr theInfo; |
theInfo = (tWindowInfoPtr) GetWRefCon ( theWindow ); |
MoveControl ( theInfo->vScrollBar, theWindow->portRect.right - kScrollBarWidthAdjust, |
theWindow->portRect.top - 1 ); |
MoveControl ( theInfo->hScrollBar, theWindow->portRect.left - 1, |
theWindow->portRect.bottom - kScrollBarWidthAdjust ); |
SizeControl ( theInfo->vScrollBar, kScrollBarWidth, |
theWindow->portRect.bottom - theWindow->portRect.top - 13 ); |
SizeControl ( theInfo->hScrollBar, theWindow->portRect.right - theWindow->portRect.left - 13, |
kScrollBarWidth ); |
maxXsize = theInfo->offscreen->portRect.right - |
((theWindow->portRect.right - kScrollBarWidthAdjust) - theWindow->portRect.left); |
maxYsize = theInfo->offscreen->portRect.bottom - |
((theWindow->portRect.bottom - kScrollBarWidthAdjust) - theWindow->portRect.top); |
SetControlMaximum ( theInfo->vScrollBar, maxYsize ); |
SetControlMaximum ( theInfo->hScrollBar, maxXsize ); |
return; |
} |
// |
// Calculates the maximum window size based on the image size and the |
// current size of the main screen. The image size is used, but resticted |
// by the current screen size. |
// |
static Point GetMaximumWindowSize ( WindowRef theWindow ) |
{ |
GDHandle theMainGDevHndl; |
Point theWindowSize, |
theImageSize; |
tWindowInfoPtr theInfo; |
theInfo = (tWindowInfoPtr) GetWRefCon ( theWindow ); |
// Calulate the image size |
theImageSize.h = theInfo->offscreen->portRect.right - theInfo->offscreen->portRect.left; |
theImageSize.v = theInfo->offscreen->portRect.bottom - theInfo->offscreen->portRect.top; |
theImageSize.h += kScrollBarWidth; |
theImageSize.v += kScrollBarWidth; |
// Calulate the screen size |
theMainGDevHndl = GetMainDevice ( ); |
theWindowSize.h = (*theMainGDevHndl)->gdRect.right - (*theMainGDevHndl)->gdRect.left; |
theWindowSize.v = (*theMainGDevHndl)->gdRect.bottom - (*theMainGDevHndl)->gdRect.top; |
theWindowSize.v -= GetMBarHeight ( ); |
// Make sure the image size is within the constraints of the screen |
theWindowSize.h = theWindowSize.h < theImageSize.h ? theWindowSize.h : theImageSize.h; |
theWindowSize.v = theWindowSize.v < theImageSize.v ? theWindowSize.v : theImageSize.v; |
return theWindowSize; |
} |
Copyright © 2003 Apple Computer, Inc. All Rights Reserved. Terms of Use | Privacy Policy | Updated: 2003-01-30