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.
wdefpatch.c
/******************************************* |
WDEF Patcher |
Steve Falkenburg MacDTS |
©1991 Apple Computer |
This snippet shows how you can add a simple extra part to a WDEF without |
writing an entire WDEF. It also shows how to access the new part via |
FindWindow(). |
6/1/92 SJF fixed a5 problem in WDEF patch (StripAddress is glue, and a5 wasn't set up) |
6/1/92 SJF fixed varCode bug that made zoom boxes not work (masked out high 8 bits) |
*******************************************/ |
#include <Windows.h> |
/* add 2 to this when checking with FindWindow() ! */ |
#define kOurHit 32 |
Boolean gInBackground; |
Boolean gDone; |
void InitStuff(void); |
void EventLoop(WindowPtr window); |
void DoDrag(WindowPtr window,Point globMouse); |
void HandleMouseDowns(EventRecord *ev); |
void HandleContent(WindowPtr theWindow,EventRecord *ev); |
void HandleUpdates(WindowPtr wind); |
void DoDeActivate(WindowPtr window,Boolean chFlag); |
void DoActivate(WindowPtr window,Boolean chFlag); |
void HandleActivates(EventRecord *ev); |
void HandleSREvt(long message); |
void DoGrow(WindowPtr window,Point globMouse); |
void PatchWindowWDEF(WindowPtr window); |
pascal long MyWDEFPatch(short varCode,WindowPtr window,short message,long param); |
void HandleOurPart(WindowPtr window); |
/* this struct allows us to insert a WDEF patch safely. It contains a jump instruction |
and stores the old handle to the WDEF |
*/ |
typedef struct { |
short jmpInst; |
ProcPtr patchAddr; |
Handle oldAddr; |
long ourA5; |
} WDEFPatch, *WDEFPatchPtr, **WDEFPatchHndl; |
void main(void) |
{ |
WindowPtr mainWindow; |
Rect bounds = {100,100,150,300}; |
gInBackground = false; |
gDone = false; |
InitStuff(); |
mainWindow = NewWindow(nil,&bounds,"\pWDEF Patcher",false,8,(WindowPtr)-1,true,0); |
PatchWindowWDEF(mainWindow); |
ShowWindow(mainWindow); |
EventLoop(mainWindow); |
} |
void InitStuff(void) |
{ |
InitGraf(&qd.thePort); |
InitFonts(); |
InitWindows(); |
InitMenus(); |
TEInit(); |
InitDialogs(nil); |
InitCursor(); |
FlushEvents(everyEvent,0); |
} |
void EventLoop(WindowPtr window) |
{ |
EventRecord ev; |
do { |
if (WaitNextEvent(everyEvent,&ev,10,nil)) { |
switch (ev.what) { |
case mouseDown: |
HandleMouseDowns(&ev); |
break; |
case updateEvt: |
HandleUpdates((WindowPtr)ev.message); |
break; |
case activateEvt: |
HandleActivates(&ev); |
break; |
case app4Evt: |
HandleSREvt(ev.message); |
break; |
} |
} |
} while (!gDone); |
} |
void HandleMouseDowns(EventRecord *ev) |
{ |
WindowPtr theWindow; |
short part; |
part = FindWindow(ev->where,&theWindow); |
switch (FindWindow(ev->where,&theWindow)) { |
case inMenuBar: |
break; |
case inSysWindow: |
SystemClick(ev,theWindow); |
break; |
case inDrag: |
DoDrag(theWindow,ev->where); |
break; |
case inGoAway: |
if (TrackGoAway(theWindow,ev->where)) { |
gDone = true; |
} |
break; |
case inContent: |
HandleContent(theWindow,ev); |
break; |
case inGrow: |
DoGrow(theWindow,ev->where); |
break; |
case kOurHit+2: // remember, we're adding 2 so the FindWindow/WDEF |
HandleOurPart(theWindow); // codes match |
break; |
} |
} |
/* handles a mouse down in our added window part */ |
void HandleOurPart(WindowPtr window) |
{ |
long final; |
SetPort(window); |
InvertRect(&window->portRect); |
while (StillDown()); |
InvertRect(&window->portRect); |
} |
/* DoDrag: Handles drag window events */ |
void DoDrag(WindowPtr window,Point globMouse) |
{ |
Rect dragRect; |
SetRect(&dragRect,-32000,-32000,32000,32000); |
DragWindow(window,globMouse,&dragRect); |
SetPort(window); |
} |
/* DoGrow: Handles grow window events */ |
void DoGrow(WindowPtr window,Point globMouse) |
{ |
long newSize; |
Rect windLimits; |
GrafPtr tempPort; |
SetRect(&windLimits,64,64,32000,32000); |
if ((newSize = GrowWindow(window,globMouse,&windLimits)) != 0) { |
GetPort(&tempPort); |
SetPort(window); |
SizeWindow(window,LoWord(newSize),HiWord(newSize),true); |
InvalRect(&window->portRect); |
SetPort(tempPort); |
} |
} |
void HandleContent(WindowPtr theWindow,EventRecord *ev) |
{ |
GrafPtr savePort; |
Point where; |
where = ev->where; |
SetPort(theWindow); |
if (theWindow != FrontWindow()) { |
SelectWindow(theWindow); |
return; |
} |
} |
void HandleUpdates(WindowPtr wind) |
{ |
GrafPtr savePort; |
GetPort(&savePort); |
SetPort(wind); |
BeginUpdate(wind); |
EraseRect(&wind->portRect); |
DrawGrowIcon(wind); |
EndUpdate(wind); |
SetPort(savePort); |
} |
void HandleActivates(EventRecord *ev) |
{ |
if ((ev->modifiers & activeFlag) != 0) { |
DoActivate((WindowPtr)ev->message,((ev->modifiers & 0x0002) != 0)); |
} |
else { |
DoDeActivate((WindowPtr)ev->message,((ev->modifiers & 0x0002) != 0)); |
} |
} |
/* DoActivate: Performs activate tasks */ |
void DoActivate(WindowPtr window,Boolean chFlag) |
{ |
DrawGrowIcon(window); |
} |
/* DoDeActivate: Performs deactivate tasks */ |
void DoDeActivate(WindowPtr window,Boolean chFlag) |
{ |
DrawGrowIcon(window); |
} |
void HandleSREvt(long message) |
{ |
if ((message >> 24) == 1) |
if ((message & 1) != 0) { |
gInBackground = false; |
SetCursor(&arrow); |
if (FrontWindow()) { |
HiliteWindow(FrontWindow(),true); |
DoActivate(FrontWindow(),true); |
} |
} |
else if (FrontWindow()) { |
gInBackground = true; |
HiliteWindow(FrontWindow(),false); |
DoDeActivate(FrontWindow(),true); |
} |
} |
/* this installs the WDEF patch into a window */ |
void PatchWindowWDEF(WindowPtr window) |
{ |
WDEFPatchHndl wdefHndl; |
WDEFPatchPtr wdefPatch; |
Handle oldAddr; |
unsigned long wdefEntry; |
wdefHndl = (WDEFPatchHndl)NewHandle(sizeof(WDEFPatch)); |
if (MemError()!=noErr) |
ExitToShell(); |
oldAddr = ((WindowPeek)window)->windowDefProc; |
if (GetMMUMode()) // 32-bit |
wdefEntry = (unsigned long)wdefHndl; |
else |
wdefEntry = (unsigned long)StripAddress(wdefHndl) | ((unsigned long)oldAddr&0xff000000); |
HLock(wdefHndl); |
wdefPatch = *wdefHndl; |
wdefPatch->oldAddr = oldAddr; |
wdefPatch->jmpInst = 0x4ef9; /*JMP*/ |
wdefPatch->patchAddr = MyWDEFPatch; |
#ifdef __SYSEQU__ |
wdefPatch->ourA5 = *(long *)CurrentA5; |
#else |
wdefPatch->ourA5 = (long)CurrentA5; |
#endif |
HUnlock(wdefHndl); |
((WindowPeek)window)->windowDefProc = (Handle)wdefEntry; |
} |
pascal long MyWDEFPatch(short varCode,WindowPtr window,short message,long param) |
{ |
WDEFPatchHndl wdPatch; |
pascal long (*wdefProc)(short varCode,WindowPtr window,short message,long param); |
Handle oldWDEF; |
long result; |
Rect ourRect,ourElementRect; |
Point *hitPt; |
Point mouse; |
long appA5,saveA5; |
wdPatch = (WDEFPatchHndl) ((WindowPeek)window)->windowDefProc; |
appA5 = (**wdPatch).ourA5; |
saveA5 = SetA5(appA5); |
ourRect = (**((WindowPeek)window)->strucRgn).rgnBBox; |
SetRect(&ourElementRect,ourRect.right-32,ourRect.top+4,ourRect.right-20,ourRect.top+15); |
oldWDEF = (**wdPatch).oldAddr; |
HLock(oldWDEF); |
wdefProc = (void *)*oldWDEF; |
wdefProc = (void *)StripAddress(wdefProc); |
result = (wdefProc)(varCode,window,message,param); |
switch (message) { |
case wDraw: |
if (((WindowPeek)window)->visible) { |
PenNormal(); // draw our part |
InsetRect(&ourElementRect,-1,0); |
EraseRect(&ourElementRect); |
InsetRect(&ourElementRect,1,0); |
FrameRect(&ourElementRect); |
InsetRect(&ourElementRect,2,2); |
FrameRect(&ourElementRect); |
} |
break; |
case wHit: |
hitPt = (Point *)¶m; // hit test our part |
if (PtInRect(*hitPt,&ourElementRect)) |
result = kOurHit; |
break; |
} |
HUnlock(oldWDEF); |
SetA5(saveA5); |
return result; |
} |
Copyright © 2003 Apple Computer, Inc. All Rights Reserved. Terms of Use | Privacy Policy | Updated: 2003-01-14