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.
CustomWindow.c
/* |
File: CustomWindow.c |
Contains: A sample on how to create a fully functional custom window for Carbon |
Written by: Karl Groethe |
Copyright: Copyright © 2000 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): |
6/28/00 created |
*/ |
#include "CustomWindow.h" |
#include <Carbon/Carbon.h> |
#define kPictureID 128 |
#define kMaskPictureID 129 |
SInt32 myWindowDef(short varCode,WindowRef window, SInt16 message, SInt32 param) |
{ |
/*------------------------------------------------------ |
This is the main entry point for the Custom Window. |
--------------------------------------------------------*/ |
switch(message){ |
case kWindowMsgDraw: |
return myWindowDraw(window,param); |
case kWindowMsgHitTest: |
return myWindowHitTest(window,param); |
case kWindowMsgInitialize: |
return myWindowInitialize(window,param); |
case kWindowMsgCleanUp: |
return myWindowCleanUp(window,param); |
case kWindowMsgDrawGrowOutline: |
return myWindowDrawGrowOutline(window,param); |
//8.0 forward |
case kWindowMsgGetFeatures: |
return myWindowGetFeatures(window,param); |
case kWindowMsgGetRegion: |
return myWindowGetRegion(window,param); |
//8.5 forward |
case kWindowMsgDragHilite: |
return myWindowDragHilite(window,param); |
case kWindowMsgModified: |
return myWindowModified(window,param); |
case kWindowMsgDrawInCurrentPort: |
return myWindowDrawInCurrentPort(window,param); |
case kWindowMsgStateChanged: |
return myWindowStateChanged(window,param); |
//carbon only |
case kWindowMsgGetGrowImageRegion: |
return myWindowGetGrowImageRegion(window,param); |
default: |
return 0; |
} |
} |
SInt32 myWindowGetFeatures(WindowRef window,SInt32 param) |
{ |
/*------------------------------------------------------ |
Define which options your custom window supports. |
--------------------------------------------------------*/ |
//just enable everything for our demo |
*(OptionBits*)param=kWindowCanGrow| |
kWindowCanZoom| |
kWindowCanCollapse| |
kWindowCanGetWindowRegion| |
kWindowHasTitleBar| |
kWindowSupportsDragHilite| |
kWindowCanDrawInCurrentPort| |
kWindowCanMeasureTitle| |
kWindowWantsDisposeAtProcessDeath| |
kWindowSupportsSetGrowImageRegion| |
kWindowDefSupportsColorGrafPort; |
return 1; |
} |
SInt32 myWindowDraw(WindowRef window,SInt32 param) |
{ |
/*------------------------------------------------------ |
Use this method to draw the window based on the value |
of param. |
wNoHit: draw the frame and attributes |
wInGoAway: hilite or unhilite GoAway box |
wInZoomIn: hilite or unhilite ZoomIn Box |
wInZoomOut: hilite or unhilite ZoomOut Box |
wInCollapseBox: hilite or unhilite Collapse Box |
--------------------------------------------------------*/ |
static Boolean hilite=FALSE; |
WindowAttributes attributes; |
if(IsWindowVisible(window)) |
{ |
switch(param){ |
case wNoHit: |
hilite=FALSE;//redrawn so no box hiliteing |
drawWindowFrame(window); |
GetWindowAttributes(window,&attributes); |
if(attributes & kWindowCloseBoxAttribute)//is there a close box? |
drawWindowCloseBox(window,hilite); |
if(attributes & kWindowFullZoomAttribute)//is there a zoom box? |
drawWindowZoomBox(window,hilite); |
if(attributes & kWindowCollapseBoxAttribute)//is there a collapse box? |
drawWindowCollapseBox(window,hilite); |
break; |
case wInGoAway: |
hilite=drawWindowCloseBox(window,!hilite); |
break; |
case wInZoomIn: |
case wInZoomOut: |
hilite=drawWindowZoomBox(window,!hilite); |
break; |
case wInCollapseBox: |
hilite=drawWindowCollapseBox(window,!hilite); |
break; |
} |
} |
return 0; |
} |
RgnHandle getWindowCloseBoxRegion(WindowRef window,RgnHandle closeBoxRegion) |
{ |
/*------------------------------------------------------ |
Define the region for the close box |
--------------------------------------------------------*/ |
SetEmptyRgn(closeBoxRegion); |
return closeBoxRegion; |
} |
RgnHandle getWindowZoomBoxRegion(WindowRef window,RgnHandle zoomBoxRegion) |
{ |
/*------------------------------------------------------ |
Define the region for the zoom box |
--------------------------------------------------------*/ |
SetEmptyRgn(zoomBoxRegion); |
return zoomBoxRegion; |
} |
RgnHandle getWindowCollapseBoxRegion(WindowRef window,RgnHandle collapseBoxRegion) |
{ |
/*------------------------------------------------------ |
Define the region for the collapse box |
--------------------------------------------------------*/ |
SetEmptyRgn(collapseBoxRegion); |
return collapseBoxRegion; |
} |
RgnHandle getWindowGrowBoxRegion(WindowRef window,RgnHandle growBoxRegion) |
{ |
/*------------------------------------------------------ |
Define the region for the Grow Box |
--------------------------------------------------------*/ |
SetEmptyRgn(growBoxRegion); |
return growBoxRegion; |
} |
RgnHandle getWindowTitleBarRegion(WindowRef window,RgnHandle titleBarRegion) |
{ |
/*------------------------------------------------------ |
Define the region for the title bar |
--------------------------------------------------------*/ |
SetEmptyRgn(titleBarRegion); |
return titleBarRegion; |
} |
RgnHandle getWindowTitleTextRegion(WindowRef window,RgnHandle titleTextRegion) |
{ |
/*------------------------------------------------------ |
Define the region for the text in the title bar |
--------------------------------------------------------*/ |
SetEmptyRgn(titleTextRegion); |
return titleTextRegion; |
} |
RgnHandle getWindowContentRegion(WindowRef window,RgnHandle contentRegion) |
{ |
/*------------------------------------------------------ |
Define the content region of our window. |
--------------------------------------------------------*/ |
SetEmptyRgn(contentRegion); |
if(!IsWindowCollapsed(window)){ |
//only define the content region when the window is |
//not collapsed |
} |
return contentRegion; |
} |
RgnHandle getWindowStructureRegion(WindowRef window, RgnHandle structureRegion) |
{ |
/*------------------------------------------------------ |
Define the structural region of our window. |
--------------------------------------------------------*/ |
static RgnHandle pictureRgn=NULL; |
static Rect pictureRect; |
Rect windowRect; |
SetEmptyRgn(structureRegion); |
if(!pictureRgn){//haven't Cached our region yet |
PicHandle myPicture=GetPicture(kMaskPictureID); |
GrafPtr origPort; |
GDHandle origDev; |
GWorldPtr pictMask; |
PixMapHandle maskBitMap; |
GetGWorld(&origPort,&origDev); |
pictureRgn=NewRgn(); |
pictureRect=(*myPicture)->picFrame; |
NewGWorld(&pictMask,1,&pictureRect,NULL,NULL,0); |
maskBitMap=GetPortPixMap(pictMask); |
LockPixels(maskBitMap); |
SetGWorld(pictMask,NULL); |
EraseRect(&pictureRect); |
DrawPicture(myPicture,&pictureRect); |
BitMapToRegion(pictureRgn,(BitMap*)*maskBitMap);//use the mask to create a region |
InsetRgn(pictureRgn,1,1); |
SetGWorld(origPort,origDev); |
UnlockPixels(maskBitMap); |
DisposeGWorld(pictMask); |
ReleaseResource((Handle)myPicture); |
} |
getCurrentPortBounds(&windowRect);//how big is the window |
CopyRgn(pictureRgn,structureRegion);//make a copy of our cached region |
MapRgn(structureRegion,&pictureRect,&windowRect);//scale it to our actual window size |
return structureRegion; |
} |
RgnHandle getWindowDragRegion(WindowRef window, RgnHandle dragRegion) |
{ |
/*------------------------------------------------------ |
Define the drag region of our window. |
--------------------------------------------------------*/ |
RgnHandle structureRegion=NewRgn(); |
RgnHandle contentRegion=NewRgn(); |
SetEmptyRgn(dragRegion); |
getWindowStructureRegion(window,structureRegion); |
getWindowContentRegion(window,contentRegion); |
//our drag region is the difference between the structural and content regions |
DiffRgn(structureRegion,contentRegion,dragRegion); |
DisposeRgn(structureRegion); |
DisposeRgn(contentRegion); |
return dragRegion; |
} |
void drawWindowFrame(WindowRef window) |
{ |
/*------------------------------------------------------ |
Draw the frame of our window. |
This function needs to draw the title bar, |
the grow box, the title string and the |
structural aspects of the window. |
--------------------------------------------------------*/ |
static GWorldPtr framePict=NULL; |
static Rect pictureRect; |
GrafPtr thePort; |
Rect frame; |
if(!framePict){//haven't cached our picture |
PicHandle myPicture=GetPicture(kPictureID); |
GrafPtr origPort; |
GDHandle origDev; |
GetGWorld(&origPort,&origDev); |
pictureRect=(*myPicture)->picFrame; |
NewGWorld(&framePict,0,&pictureRect,NULL,NULL,0); |
SetGWorld(framePict,NULL); |
DrawPicture(myPicture,&pictureRect); |
SetGWorld(origPort,origDev); |
ReleaseResource((Handle)myPicture); |
} |
getCurrentPortBounds(&frame); |
GetPort(&thePort); |
CopyBits(GetPortBitMapForCopyBits(framePict), |
GetPortBitMapForCopyBits(thePort), |
&pictureRect,&frame,srcCopy,NULL);//draw our picture |
myWindowDrawGrowBox(window,0);//draw grow box as part of frame |
if(IsWindowHilited(window)) |
{ |
//do any hilighting |
} |
} |
Boolean drawWindowCloseBox(WindowRef window, Boolean hilite) |
{ |
/*------------------------------------------------------ |
This function draws the close box. |
If hilite is true it draws the hiliting as well. |
--------------------------------------------------------*/ |
RgnHandle closeBoxRegion=NewRgn(); |
getWindowCloseBoxRegion(window,closeBoxRegion); |
EraseRgn(closeBoxRegion);//clear away old |
//draw close box |
if(hilite) |
{ |
//do hilighting |
} |
DisposeRgn(closeBoxRegion); |
return hilite; |
} |
Boolean drawWindowZoomBox(WindowRef window, Boolean hilite) |
{ |
/*------------------------------------------------------ |
This function draws the zoom box. |
If hilite is true it draws the hiliting as well. |
--------------------------------------------------------*/ |
RgnHandle zoomBoxRegion=NewRgn(); |
getWindowZoomBoxRegion(window,zoomBoxRegion); |
EraseRgn(zoomBoxRegion);//clear away old |
//draw zoom Box |
if(hilite) |
{ |
//do hilighting |
} |
DisposeRgn(zoomBoxRegion); |
return hilite; |
} |
Boolean drawWindowCollapseBox(WindowRef window, Boolean hilite) |
{ |
/*------------------------------------------------------ |
This function draws the collapse box. |
If hilite is true it draws the hiliting as well. |
--------------------------------------------------------*/ |
RgnHandle collapseBoxRegion=NewRgn(); |
getWindowCollapseBoxRegion(window,collapseBoxRegion); |
EraseRgn(collapseBoxRegion);//clear away old stuff |
if(hilite){ |
//do hilighting |
} |
DisposeRgn(collapseBoxRegion); |
return hilite; |
} |
RgnHandle getWindowUpdateRegion(WindowRef window, RgnHandle updateRegion) |
{ |
return updateRegion; |
} |
SInt32 myWindowHitTest(WindowRef window,SInt32 param) |
{ |
/*------------------------------------------------------ |
Determine the region of the window which was hit |
--------------------------------------------------------*/ |
Point hitPoint; |
static RgnHandle tempRgn=nil; |
if(!tempRgn) tempRgn=NewRgn(); |
SetPt(&hitPoint,LoWord(param),HiWord(param));//get the point clicked |
if(IsWindowHilited(window)){ //make sure the window is in front for these |
if(PtInRgn(hitPoint,getWindowGrowBoxRegion(window,tempRgn)))//in GrowBox? |
return wInGrow; |
if(PtInRgn(hitPoint,getWindowCloseBoxRegion(window,tempRgn)))//in the Close Box? |
return wInGoAway; |
if(PtInRgn(hitPoint,getWindowZoomBoxRegion(window,tempRgn)))//in the Zoom Box? |
return wInZoomOut; |
//Mac OS 8.0 or later |
if(PtInRgn(hitPoint,getWindowCollapseBoxRegion(window,tempRgn)))//in the Collapse Box? |
return wInCollapseBox; |
} |
//Mac OS 8.5 or later |
if(PtInRgn(hitPoint,getWindowContentRegion(window,tempRgn))) //in window content region? |
return wInContent; |
if(PtInRgn(hitPoint,getWindowDragRegion(window,tempRgn)))//in window drag region? |
return wInDrag; |
return wNoHit;//no significant area was hit. |
} |
SInt32 myWindowInitialize(WindowRef window,SInt32 param) |
{ |
/*------------------------------------------------------ |
perform any initialization for your window here |
--------------------------------------------------------*/ |
return 0; |
} |
SInt32 myWindowCleanUp(WindowRef window,SInt32 param) |
{ |
/*------------------------------------------------------ |
dispose of anything allocated in Initialization |
--------------------------------------------------------*/ |
return 0; |
} |
SInt32 myWindowDrawGrowBox(WindowRef window,SInt32 param) |
{ |
/*------------------------------------------------------ |
This function draws the grow box of the window |
--------------------------------------------------------*/ |
RgnHandle growBoxRegion=NewRgn(); |
getWindowGrowBoxRegion(window,growBoxRegion); |
//draw grow box here |
return 0; |
} |
SInt32 myWindowGetRegion(WindowRef window,SInt32 param) |
{ |
/*------------------------------------------------------ |
Define each of the window's regions |
--------------------------------------------------------*/ |
GetWindowRegionPtr rgnRec=(GetWindowRegionPtr)param; |
switch(rgnRec->regionCode){ |
case kWindowTitleBarRgn: |
getWindowTitleBarRegion(window,rgnRec->winRgn); |
break; |
case kWindowTitleTextRgn: |
getWindowTitleTextRegion(window,rgnRec->winRgn); |
break; |
case kWindowCloseBoxRgn: |
getWindowCloseBoxRegion(window,rgnRec->winRgn); |
break; |
case kWindowZoomBoxRgn: |
getWindowZoomBoxRegion(window,rgnRec->winRgn); |
break; |
case kWindowDragRgn: |
getWindowDragRegion(window,rgnRec->winRgn); |
break; |
case kWindowGrowRgn: |
getWindowGrowBoxRegion(window,rgnRec->winRgn); |
break; |
case kWindowCollapseBoxRgn: |
getWindowCollapseBoxRegion(window,rgnRec->winRgn); |
break; |
case kWindowStructureRgn: |
getWindowStructureRegion(window,rgnRec->winRgn); |
break; |
case kWindowContentRgn: |
getWindowContentRegion(window,rgnRec->winRgn); |
break; |
//Carbon Forward |
case kWindowUpdateRgn: |
getWindowUpdateRegion(window,rgnRec->winRgn); |
break; |
default: |
return errWindowRegionCodeInvalid; |
} |
return noErr; |
} |
SInt32 myWindowDragHilite(WindowRef window,SInt32 param) |
{ |
/*------------------------------------------------------ |
Hilight the window to show support for |
drag-and-drop. |
--------------------------------------------------------*/ |
if(param){ |
//hilite window |
}else{ |
//unhilight window |
} |
return 0; |
} |
SInt32 myWindowModified(WindowRef window,SInt32 param) |
{ |
/*------------------------------------------------------ |
Called when a document's "modified" bit is changed |
--------------------------------------------------------*/ |
if(param){ |
//document has been modified |
}else{ |
//document has been saved |
} |
return 0; |
} |
SInt32 myWindowDrawInCurrentPort(WindowRef window,SInt32 param) |
{ |
/*------------------------------------------------------ |
same as myWindowDraw but must draw in current port. |
myWindowDraw is defined to draw in the current port |
so just call it directly. |
--------------------------------------------------------*/ |
myWindowDraw(window,param); |
return 0; |
} |
SInt32 myWindowStateChanged(WindowRef window,SInt32 param) |
{ |
/*------------------------------------------------------ |
use this method if you need notification of a state |
change after the internal data has been altered but |
before the window is updated on the screen |
--------------------------------------------------------*/ |
if(param & kWindowStateTitleChanged){ |
//the Title Has changed |
} |
return 0; |
} |
SInt32 myWindowDrawGrowOutline(WindowRef window,SInt32 Param) |
{ |
/*------------------------------------------------------ |
Draw the window's grow outline |
--------------------------------------------------------*/ |
return 0; |
} |
SInt32 myWindowGetGrowImageRegion(WindowRef window,SInt32 param) |
{ |
/*------------------------------------------------------ |
Get region to xor during grow/resize. |
--------------------------------------------------------*/ |
GetGrowImageRegionRec* rgnRec=(GetGrowImageRegionRec*)param; |
#pragma unused(rgnRec) |
return noErr; |
} |
void getCurrentPortBounds(Rect* inRect) |
{ |
/*------------------------------------------------------ |
Simple utility function to get the bounds of the |
current port. |
--------------------------------------------------------*/ |
CGrafPtr thePort; |
GetPort(&thePort); |
GetPortBounds(thePort,inRect); |
} |
Copyright © 2003 Apple Computer, Inc. All Rights Reserved. Terms of Use | Privacy Policy | Updated: 2003-01-30