/
CustomWindow.c
executable file
·521 lines (483 loc) · 19 KB
/
CustomWindow.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
/*
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);
}