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.
NewCCursor.c
/*******************************************/ |
/* */ |
/* File: NewCCursor.c */ |
/* */ |
/* Program: NewCCursor */ |
/* */ |
/* By: Jason Hodges Harris */ |
/* */ |
/* Version: 1.0.1 */ |
/* */ |
/*******************************************/ |
// This Code snippet creates from scratch both Black & White 'CURS' |
// and color 'crsr' Cursors from PICT resources. |
// Mac Toolbox headers |
#ifndef __DESK__ |
#include <Desk.h> |
#endif |
#ifndef __DIALOGS__ |
#include <Dialogs.h> |
#endif |
#ifndef __DISKINIT__ |
#include <DiskInit.h> |
#endif |
#ifndef __EVENTS__ |
#include <Events.h> |
#endif |
#ifndef __FILES__ |
#include <Files.h> |
#endif |
#ifndef __FONTS__ |
#include <Fonts.h> |
#endif |
#ifndef __MEMORY__ |
#include <Memory.h> |
#endif |
#ifndef __MENUS__ |
#include <Menus.h> |
#endif |
#ifndef __QDOFFSCREEN__ |
#include <QDOffscreen.h> |
#endif |
#ifndef __RESOURCES__ |
#include <Resources.h> |
#endif |
#ifndef __SCRIPT__ |
#include <Script.h> |
#endif |
#ifndef __SEGLOAD__ |
#include <SegLoad.h> |
#endif |
#ifndef __STANDARDFILE__ |
#include <StandardFile.h> |
#endif |
#ifndef __STRING__ |
#include <String.H> |
#endif |
#ifndef __TEXTEDIT__ |
#include <TextEdit.h> |
#endif |
#ifndef __TEXTUTILS__ |
#include <TextUtils.h> |
#endif |
#ifndef __TOOLUTILS__ |
#include <ToolUtils.h> |
#endif |
#ifndef __TYPES__ |
#include <Types.h> |
#endif |
#ifndef __WINDOWS__ |
#include <Windows.h> |
#endif |
#define HiWrd(aLong) (((aLong) >> 16) & 0xFFFF) |
#define LoWrd(aLong) ((aLong) & 0xFFFF) |
// menu defs |
#define mApple 128 |
#define iAbout 1 |
#define mFile 129 |
#define iQuit 1 |
#define mTest 130 |
#define iBWCursor 1 |
#define iCCursor 2 |
// Global variables |
CCrsrHandle gNewCCursorHndl = nil; |
Cursor gNewCursor; |
Boolean gQuitFlag = false, |
gCustomCursor = false, |
gCursorDepth = 0; |
// function prototypes |
void InitToolbox(void); |
void MainEventLoop(void); |
void HandleKeyPress(EventRecord *myEvent); |
void HandleMenuCommand(long menuResult); |
void CreateCursor(short depth); |
// main program function |
int main() |
{ |
InitToolbox() ; |
MainEventLoop(); |
return 0; |
} |
// toolbox initialisation |
void InitToolbox() |
{ |
OSErr retCode; |
long gestResponse; |
Handle menuBar = nil; |
EventRecord myEvent; |
short count; |
MaxApplZone(); |
InitGraf((Ptr) &qd.thePort); |
InitFonts(); |
InitWindows(); |
InitMenus(); |
TEInit(); |
InitDialogs(0L); |
InitCursor(); |
menuBar = GetNewMBar(128); |
if (menuBar == nil) |
ExitToShell(); |
SetMenuBar(menuBar); |
DisposHandle(menuBar); |
AddResMenu(GetMHandle(mApple), 'DRVR'); // Add DA names to Apple menu, ID 128 |
DrawMenuBar(); |
} |
// Event processing |
void MainEventLoop() |
{ |
EventRecord myEvent; |
WindowPtr window; |
short thePart; |
Rect screenRect; |
Point aPoint = {100, 100}; |
GrafPtr oldPort ; |
while( !gQuitFlag ) |
{ |
if (WaitNextEvent( everyEvent, &myEvent, 0, nil )) |
{ |
switch (myEvent.what) |
{ |
case mouseDown: |
thePart = FindWindow( myEvent.where, &window ); |
switch( thePart ) |
{ |
case inMenuBar: |
HandleMenuCommand(MenuSelect(myEvent.where)); |
break; |
case inDrag: |
break ; |
case inContent: |
break ; |
case inGoAway: |
break ; |
default: |
break ; |
} |
break ; |
case updateEvt: |
break ; |
case keyDown: |
case autoKey: |
HandleKeyPress(&myEvent); |
break; |
case diskEvt: |
if ( HiWrd(myEvent.message) != noErr ) |
(void) DIBadMount(aPoint, myEvent.message); |
break; |
case osEvt: |
case activateEvt: |
// restore custom cursor on application activate event |
if (myEvent.message>>24 == resumeFlag) |
{ |
if (gCustomCursor && gCursorDepth == 1) |
SetCursor(&gNewCursor); |
else if (gCustomCursor && gCursorDepth == 8) |
SetCCursor(gNewCCursorHndl); |
} |
break; |
} |
} |
} |
} |
void HandleKeyPress(EventRecord *myEvent) |
{ |
char key; |
long lByteCnt ; |
key = myEvent->message & charCodeMask; |
if ( myEvent->modifiers & cmdKey ) // Cmd key down? |
{ |
HandleMenuCommand(MenuKey(key)); |
} |
} |
// process menubar commands |
void HandleMenuCommand(long menuResult) |
{ |
short menuID; |
short menuItem; |
Str255 daName; |
DialogPtr theDialog ; |
short itemHit ; |
Rect cursorRect = {0,0,16,16}; |
menuID = HiWrd(menuResult); |
menuItem = LoWrd(menuResult); |
switch ( menuID ) |
{ |
case mApple: |
switch ( menuItem ) |
{ |
case iAbout: |
theDialog = GetNewDialog ( 128, nil, (WindowPtr)-1 ); |
do { |
ModalDialog ( nil, &itemHit ); |
} while( itemHit != ok ) ; |
DisposDialog ( theDialog ); |
break; |
default: |
GetItem(GetMHandle(mApple), menuItem, daName); |
(void) OpenDeskAcc(daName); |
break; |
} |
break; |
case mFile: |
switch ( menuItem ) |
{ |
case iQuit: |
gQuitFlag = true; |
break; |
} |
break; |
case mTest: |
switch (menuItem) |
{ |
case iBWCursor: |
CreateCursor(1); // create 1 bit cursor from PICT rsrc |
break ; |
case iCCursor: |
CreateCursor(8); // create 8 bit cursor from PICT rsrc |
break; |
} |
break; |
} |
HiliteMenu(0); // Unhighlight whatever MenuSelect or MenuKey hilited |
} |
// function to create from scratch either a 1 bit CURS or an 8 bit crsr |
// See Inside Macintosh, "Imaging With QuickDraw", Ch 8 Cursor Utilities, |
// for an in depth explanation of the crsr and CURS structures. |
void CreateCursor(short depth) |
{ |
PixMapHandle myPixmap = nil; |
GDHandle oldDevice = nil; |
PicHandle cursorPict = nil; |
GWorldPtr myGWorldPtr = nil, |
oldPort = nil; |
Ptr cursorBaseAddr = nil; |
QDErr myError; |
Rect cursorRect = {0,0,16,16}; |
short pixRowbytes, |
count, |
count2, |
maskInfo, |
tempInfo; |
char myAddrMode = true32b; |
GetGWorld(&oldPort,&oldDevice); |
gCursorDepth = depth; |
switch (depth) |
{ |
case 1: |
cursorPict=GetPicture(1000); // 16*16 1 bit B/W PICT to be used as cursor |
break; |
case 8: |
cursorPict=GetPicture(1001); //16*16 8 bit color PICT to be used as cursor |
break; |
} |
if (cursorPict==nil) |
{ |
// handle GWorld creation errors here |
DebugStr("\pFailed to get PICT rsrc"); |
return; |
} |
// create GWorld to temp hold of PICT rsrc for conversion. |
myError=NewGWorld(&myGWorldPtr,depth,&cursorRect,nil,nil,0); |
if (myError) |
{ |
// handle GWorld creation errors here |
DebugStr("\pFailed to allocate GWorld."); |
return; |
} |
myPixmap = GetGWorldPixMap(myGWorldPtr); // get GWorld PixMap |
SwapMMUMode (&myAddrMode); // switch to 32 bit mode |
LockPixels(myPixmap); // lock down PixMap |
SetGWorld(myGWorldPtr,nil); // set port to GWorld |
HLockHi((Handle)cursorPict); |
DrawPicture(cursorPict,&cursorRect); // draw PICT to GWorld |
HUnlock((Handle)cursorPict); |
ReleaseResource((Handle)cursorPict); // release PICT as no longer required |
GetGWorld(&oldPort,&oldDevice); // reset port |
pixRowbytes = (**myPixmap).rowBytes & 0x3FFF; // get GWorld PixMap rowBytes |
cursorBaseAddr = (**myPixmap).baseAddr; // get GWorld PixMap base addr |
switch (depth) |
{ |
case 1: // B/W Cursor |
for (count=0;count<16;count++) |
{ |
memcpy (&gNewCursor.data[count],cursorBaseAddr,2); // copy pict data into cursor struct |
gNewCursor.mask[count] = gNewCursor.data[count]; // mask = data |
cursorBaseAddr+=pixRowbytes; |
} |
gNewCursor.hotSpot.v = 15; |
gNewCursor.hotSpot.h = 0; |
gCustomCursor = true; |
SetCursor(&gNewCursor); |
break; |
case 8: // Color Cursor |
// create new Handle to hold Color Table |
if (gNewCCursorHndl !=nil) |
{ |
// dispose of old handles if already allocated. Stops memory leaks. |
DisposeHandle((Handle)(**gNewCCursorHndl).crsrData); |
DisposeHandle((Handle)(**(**gNewCCursorHndl).crsrMap).pmTable); |
DisposeHandle((Handle)(**gNewCCursorHndl).crsrMap); |
DisposeHandle((Handle)gNewCCursorHndl); |
} |
gNewCCursorHndl = (CCrsrHandle) NewHandle(sizeof(CCrsr)); // create crsr handle |
(**gNewCCursorHndl).crsrType = 0x8001; // color cursor |
(**gNewCCursorHndl).crsrMap = NewPixMap(); |
(**(**gNewCCursorHndl).crsrMap).bounds = cursorRect; |
(**(**gNewCCursorHndl).crsrMap).rowBytes = 16; // 16 (8 bits deep) pixels wide |
(**(**gNewCCursorHndl).crsrMap).pixelSize = 8; // 8 bits deep |
SetHandleSize((Handle)(**(**gNewCCursorHndl).crsrMap).pmTable,(sizeof(ColorTable)+(sizeof(ColorSpec)*256))); |
// copy color table from Pict GWorld to Color Cursor |
HLock((Handle)(**(**gNewCCursorHndl).crsrMap).pmTable); |
HLock((Handle)(**myPixmap).pmTable); |
BlockMove((*(**myPixmap).pmTable), |
(*(**(**gNewCCursorHndl).crsrMap).pmTable), |
(sizeof(ColorTable)+(sizeof(ColorSpec)*256))); |
HUnlock((Handle)(**(**gNewCCursorHndl).crsrMap).pmTable); |
HUnlock((Handle)(**myPixmap).pmTable); |
CTabChanged((**(**gNewCCursorHndl).crsrMap).pmTable); |
(**gNewCCursorHndl).crsrData = NewHandle(256); |
HLock((**gNewCCursorHndl).crsrData); |
// copy data from PICT into crsr to build CCursor |
for (count=0;count<16;count++) |
{ |
memcpy ((*(**gNewCCursorHndl).crsrData)+(16*count),cursorBaseAddr,16); // get data type |
cursorBaseAddr+=pixRowbytes; |
} |
(**gNewCCursorHndl).crsrXValid = 0; // Cursor to be re expanded |
(**gNewCCursorHndl).crsrXHandle = 0; // reserved |
// create crsr mask |
for (count=0;count<16;count++) |
{ |
maskInfo=0; |
for (count2=0;count2<16;count2++) |
{ |
tempInfo = *((*(**gNewCCursorHndl).crsrData)+(16*count+count2)); |
if (tempInfo) // if image byte has value mask relevant bit |
maskInfo = maskInfo | 1<<(15-count2); |
} |
(**gNewCCursorHndl).crsrMask[count] = maskInfo; // place current line of mask into struct |
} |
HUnlock((**gNewCCursorHndl).crsrData); |
(**gNewCCursorHndl).crsrHotSpot.v = 15; |
(**gNewCCursorHndl).crsrHotSpot.h = 0; |
(**gNewCCursorHndl).crsrXTable = 0; // reserved |
gCustomCursor = true; |
SetCCursor(gNewCCursorHndl); |
break; |
} |
UnlockPixels(myPixmap); |
DisposeGWorld(myGWorldPtr); // Clean up deallocation of GWorld |
SwapMMUMode (&myAddrMode); // restore addressing mode |
} |
Copyright © 2003 Apple Computer, Inc. All Rights Reserved. Terms of Use | Privacy Policy | Updated: 2003-01-14