|
|
1.1 root 1: /*--------------------------------------------------------*\
2: SHAPES.C - displays rotating, variable size 3D shapes
3: \*--------------------------------------------------------*/
4:
5: #include <stddef.h>
6: #include <stdlib.h>
7: #include <os2.h>
8: #include "shapes.h"
9: #include "sstruct.h"
10:
11: #define WM_END_CHILD (WM_USER + 0)
12:
13: VOID CreateParent ();
14: VOID CreateChild ();
15:
16: INT iNextValidWindow (INT);
17: INT iQueryChild (HWND);
18: INT iNextFreeChild ();
19:
20: MRESULT EXPENTRY ParentWndProc (HWND, USHORT, MPARAM, MPARAM);
21: MRESULT EXPENTRY ChildWndProc (HWND, USHORT, MPARAM, MPARAM);
22:
23: extern VOID ChangeScale (PSV);
24: extern VOID ChangeShapePosition (PSV);
25: extern VOID DrawAndFill (PSV);
26:
27: extern SHAPE rgshape []; /* table of shape definitions */
28: extern INT shapeMax; /* max number of different shapes */
29:
30: INT ishapeParent = 0; /* current shape in parent window */
31:
32: /*
33: "rgpsv" is a table of pointers to shape variables. For each open
34: window there is one instance of these variables. (see SHAPEVARS structure)
35: */
36:
37: PSV rgpsv [MAX_WINDOWS];
38:
39: INT iMaxChild = 0; /* max child index */
40: INT iChildCreate; /* index of child being created */
41:
42: BOOL fCloseParent = FALSE; /* true when parent window is closed */
43:
44: extern INT yPelAdjust = 1024; /* adjustment for varying pixel shape */
45:
46: LONG cxScreen, cyScreen; /* size of full screen */
47:
48: HAB hab;
49: HWND hwndMenu;
50: CHAR szClassNameParent[] = "Shapes";
51: CHAR szClassNameChild[] = "Child";
52:
53:
54: /*
55: * Main:
56: * - main loop which receives/sends messages for the parent and child
57: * windows
58: * - when no messages are waiting in the queue, the next shape is redrawn
59: */
60:
61: main()
62: {
63: HMQ hmq;
64: QMSG qmsg;
65: BOOL fNotDone = TRUE;
66: INT iWindow = 0;
67:
68: hab = WinInitialize (NULL);
69: hmq = WinCreateMsgQueue (hab, 0);
70:
71: WinRegisterClass (hab, szClassNameParent, ParentWndProc,
72: CS_SIZEREDRAW,
73: 0 );
74:
75: WinRegisterClass (hab, szClassNameChild, ChildWndProc,
76: CS_SIZEREDRAW,
77: 0 );
78:
79: CreateParent ();
80:
81: /* receive/send messages until parent window is closed */
82:
83: while (fNotDone)
84: {
85: if (WinPeekMsg (hab, &qmsg, NULL, 0, 0, PM_REMOVE) )
86:
87: if (qmsg.msg == WM_QUIT && fCloseParent)
88: fNotDone = FALSE;
89: else
90: WinDispatchMsg (hab, &qmsg);
91: else
92: {
93: /* get next window and redraw its shape */
94:
95: iWindow = iNextValidWindow (iWindow);
96: if (!rgpsv [iWindow]->fShaded)
97: ChangeShapePosition (rgpsv [iWindow]);
98: }
99: }
100:
101: /* destroy remaining open windows */
102:
103: iWindow = 0;
104: do
105: {
106: iWindow = iNextValidWindow (iWindow);
107: GpiDestroyPS (rgpsv [iWindow]->hpsClient);
108: WinDestroyWindow (rgpsv [iWindow]->hwndFrame);
109: }
110: while (iWindow != 0);
111:
112: WinDestroyMsgQueue (hmq);
113: WinTerminate (hab);
114:
115: return 0;
116: }
117:
118:
119: /*
120: * CreateParent:
121: * - allocate storage for shape variables
122: * - create the parent window
123: */
124:
125: VOID CreateParent()
126: {
127: PSV psv;
128: SHAPE *pshape;
129: ULONG CtlData;
130:
131: psv = (PSV) malloc (sizeof (SHAPEVARS));
132: rgpsv [0] = psv;
133: pshape = &rgshape [ishapeParent];
134:
135: psv->iShape = ishapeParent;
136: psv->rgptOld = (POINTL *) malloc ( MAX_POINTS * sizeof (POINTL) );
137: psv->rgptNew = (POINTL *) malloc ( MAX_POINTS * sizeof (POINTL) );
138: psv->fShaded = FALSE;
139: psv->fErased = TRUE;
140: psv->fClipping = (pshape->pobject->rgface != NULL);
141: psv->fVarySize = FALSE;
142: psv->fPerspective = TRUE;
143: psv->pt2LightAng.x = 0;
144: psv->pt2LightAng.y = 0;
145: psv->pt3Angle = pshape->pinit->pt3Angle;
146: psv->pt3AngVel = pshape->pinit->pt3AngVel;
147: psv->pt3SizeAng = pshape->pinit->pt3SizeAng;
148:
149: CtlData = FCF_TITLEBAR
150: | FCF_SIZEBORDER | FCF_MINMAX
151: | FCF_SYSMENU | FCF_MENU;
152: psv->hwndFrame = WinCreateStdWindow(
153: HWND_DESKTOP,
154: WS_VISIBLE | FS_ICON | FS_ACCELTABLE,
155: &CtlData,
156: szClassNameParent,
157: szClassNameParent,
158: 0L,
159: NULL,
160: ID_RESOURCE,
161: &psv->hwndClient );
162:
163: hwndMenu = WinWindowFromID (psv->hwndFrame, FID_MENU);
164: }
165:
166:
167: /*
168: * CreateChild:
169: * - allocate storage for shape variables
170: * - initialize variables using the parents variables
171: * - create a child window
172: */
173:
174: VOID CreateChild(
175: INT iNewChild )
176: {
177: PSV psv;
178: SHAPE *pshape;
179: ULONG CtlData;
180:
181: psv = (PSV) malloc (sizeof (SHAPEVARS));
182: rgpsv [iNewChild] = psv;
183: pshape = &rgshape [ishapeParent];
184:
185: psv->iShape = ishapeParent;
186: psv->rgptOld = (POINTL *) malloc (
187: pshape->pobject->cPoints * sizeof (POINTL) );
188: psv->rgptNew = (POINTL *) malloc (
189: pshape->pobject->cPoints * sizeof (POINTL) );
190: psv->fShaded = rgpsv[0]->fShaded;
191: psv->fErased = TRUE;
192: psv->fClipping = rgpsv[0]->fClipping;
193: psv->fVarySize = rgpsv[0]->fVarySize;
194: psv->fPerspective = rgpsv[0]->fPerspective;
195: psv->pt2LightAng = rgpsv[0]->pt2LightAng;
196: psv->pt3Angle = rgpsv[0]->pt3Angle;
197: psv->pt3AngVel = rgpsv[0]->pt3AngVel;
198: psv->pt3SizeAng = rgpsv[0]->pt3SizeAng;
199:
200: iChildCreate = iNewChild;
201: CtlData = FCF_TITLEBAR | FCF_SIZEBORDER | FCF_MINMAX | FCF_SYSMENU;
202: psv->hwndFrame = WinCreateStdWindow(
203: HWND_DESKTOP,
204: WS_VISIBLE,
205: &CtlData,
206: szClassNameChild,
207: pshape->szName,
208: 0L,
209: NULL,
210: 0,
211: &psv->hwndClient );
212: }
213:
214:
215: /*
216: * iNextValidWindow:
217: * - get the window index which is greater than a given index
218: * - if no indexes are greater then return the index for
219: * the parent (first) window
220: */
221:
222: INT iNextValidWindow (
223: INT iWindow )
224: {
225: INT i;
226:
227: for (i = iWindow + 1; i <= iMaxChild; i++)
228: if (rgpsv [i] != NULL)
229: return i;
230: return 0;
231: }
232:
233:
234: /*
235: * iQueryChild:
236: * - get the window index associated with a window handle
237: * - return 0 if window handle not found
238: */
239:
240: INT iQueryChild (
241: HWND hwnd )
242: {
243: INT i;
244:
245: for (i = 1; i <= iMaxChild; i++)
246: if (rgpsv [i] != NULL && rgpsv [i]->hwndClient == hwnd)
247: return i;
248: return 0;
249: }
250:
251:
252: /*
253: * iNextFreeChild:
254: * - get a window index which is free (not currently used)
255: * - return 0 if no indexes are free
256: */
257:
258: INT iNextFreeChild ()
259: {
260: INT i;
261:
262: for (i = 1; i < MAX_WINDOWS; i++)
263: if (rgpsv [i] == NULL)
264: return i;
265: return 0;
266: }
267:
268:
269: /*
270: * ArrangeWindows:
271: * - change position and size of windows so that they fill the screen
272: */
273:
274: void ArrangeWindows ()
275: {
276: static SWP rgswp [MAX_WINDOWS];
277: INT cWnd = 0;
278: INT iWindow = 0;
279: static INT rgcWndsWide [MAX_WINDOWS] =
280: { 1,2,2,2,3,3,3,3 };
281: static INT rgcWndsHigh [3 * MAX_WINDOWS] =
282: { 1,0,0, 1,1,0, 2,1,0, 2,2,0, 2,1,2, 2,2,2, 2,3,2, 3,2,3 };
283: INT i;
284: INT xWndPos, yWndPos;
285: INT iWide, iHigh;
286:
287: /* initialize each SWP entry - one entry per window */
288:
289: do
290: {
291: iWindow = iNextValidWindow (iWindow);
292: rgswp [cWnd].fs = SWP_SIZE | SWP_MOVE | SWP_ZORDER | SWP_ACTIVATE;
293: rgswp [cWnd].hwndInsertBehind = HWND_TOP;
294: rgswp [cWnd].hwnd = rgpsv [iWindow]->hwndFrame;
295: cWnd++;
296: }
297: while (iWindow != 0);
298:
299: /* calculate each window size and position */
300:
301: iWide = cWnd - 1;
302: iHigh = (cWnd - 1) * 3;
303: xWndPos = 0;
304: yWndPos = rgcWndsHigh [iHigh] - 1;
305:
306: for (i = 0; i < cWnd; i++)
307: {
308: rgswp [i].cx = (INT) (cxScreen / rgcWndsWide [iWide]);
309: rgswp [i].cy = (INT) (cyScreen / rgcWndsHigh [iHigh + xWndPos]);
310: rgswp [i].x = rgswp [i].cx * xWndPos;
311: rgswp [i].y = rgswp [i].cy * yWndPos;
312:
313: if (yWndPos-- == 0)
314: {
315: xWndPos++;
316: yWndPos = rgcWndsHigh [iHigh + xWndPos] - 1;
317: }
318: }
319:
320: /* reposition all windows */
321:
322: WinSetMultWindowPos (hab, rgswp, cWnd);
323: }
324:
325:
326: /*
327: * AboutDlgProc:
328: * - simple 'About' dialog box
329: */
330:
331: MRESULT EXPENTRY AboutDlgProc(
332: HWND hwnd,
333: USHORT msg,
334: MPARAM mp1,
335: MPARAM mp2 )
336: {
337: switch (msg)
338: {
339: case WM_COMMAND:
340: switch (SHORT1FROMMP (mp1) )
341: {
342: case DID_OK:
343: case DID_CANCEL:
344: WinDismissDlg (hwnd, TRUE);
345: break;
346:
347: default:
348: break;
349: }
350: break;
351:
352: default:
353: return WinDefDlgProc (hwnd, msg, mp1, mp2);
354: }
355: return FALSE;
356: }
357:
358:
359: /*
360: * LightSourceDlgProc:
361: * - allows the user to change the angle of the light source
362: */
363:
364: MRESULT EXPENTRY LightSourceDlgProc(
365: HWND hwnd,
366: USHORT msg,
367: MPARAM mp1,
368: MPARAM mp2 )
369: {
370: PSV psv;
371: INT iNewPosition;
372: INT cAddToPos;
373:
374: switch (msg)
375: {
376: case WM_INITDLG:
377: psv = rgpsv [0];
378:
379: /* Set angle ranges from 0 to 180 */
380:
381: WinSendDlgItemMsg (hwnd, IDD_LIGHTANG_X, SBM_SETSCROLLBAR,
382: MPFROMP (psv->pt2LightAng.x + 90),
383: MPFROM2SHORT (0, 180) );
384: WinSendDlgItemMsg (hwnd, IDD_LIGHTANG_Y, SBM_SETSCROLLBAR,
385: MPFROMP (psv->pt2LightAng.y + 90),
386: MPFROM2SHORT (0, 180) );
387: break;
388:
389: case WM_HSCROLL:
390: switch (SHORT2FROMMP (mp2) )
391: {
392: case SB_LINELEFT:
393: cAddToPos = -5;
394: break;
395: case SB_LINERIGHT:
396: cAddToPos = 5;
397: break;
398: case SB_PAGELEFT:
399: cAddToPos = -30;
400: break;
401: case SB_PAGERIGHT:
402: cAddToPos = 30;
403: break;
404: default:
405: cAddToPos = 0;
406: break;
407: }
408: if (SHORT2FROMMP (mp2) == SB_SLIDERPOSITION)
409: iNewPosition = SHORT1FROMMP (mp2);
410: else
411: iNewPosition =
412: (INT) WinSendDlgItemMsg (hwnd, SHORT1FROMMP (mp1),
413: SBM_QUERYPOS, 0L, 0L)
414: + cAddToPos;
415:
416: /* Update slider position */
417:
418: WinSendDlgItemMsg (hwnd, SHORT1FROMMP (mp1), SBM_SETPOS,
419: MPFROMP (iNewPosition), NULL);
420: break;
421:
422: case WM_COMMAND:
423: switch (SHORT1FROMMP (mp1) )
424: {
425: case DID_OK:
426: psv = rgpsv [0];
427:
428: /* Accept new angles (range -90 to 90) */
429:
430: psv->pt2LightAng.x = (INT) WinSendDlgItemMsg (hwnd,
431: IDD_LIGHTANG_X, SBM_QUERYPOS, 0L, 0L);
432: psv->pt2LightAng.x -= 90;
433:
434: psv->pt2LightAng.y = (INT) WinSendDlgItemMsg (hwnd,
435: IDD_LIGHTANG_Y, SBM_QUERYPOS, 0L, 0L);
436: psv->pt2LightAng.y -= 90;
437:
438: WinDismissDlg (hwnd, TRUE);
439: break;
440:
441: case DID_CANCEL:
442: WinDismissDlg (hwnd, FALSE);
443: break;
444:
445: default:
446: break;
447: }
448: break;
449:
450: default:
451: return WinDefDlgProc (hwnd, msg, mp1, mp2);
452: }
453: return FALSE;
454: }
455:
456:
457: /*
458: * RotationDlgProc:
459: * - allows the user to change the angle and angular velocity of
460: * a shape in the parent window
461: */
462:
463: MRESULT EXPENTRY RotationDlgProc(
464: HWND hwnd,
465: USHORT msg,
466: MPARAM mp1,
467: MPARAM mp2 )
468: {
469: PSV psv;
470: INT iNewPosition;
471: INT cAddToPos;
472: INT cLineSize, cPageSize;
473:
474: switch (msg)
475: {
476: case WM_INITDLG:
477: psv = rgpsv [0];
478:
479: /* Set angle ranges from 0 to 359 */
480:
481: WinSendDlgItemMsg (hwnd, IDD_ANGLE_X, SBM_SETSCROLLBAR,
482: MPFROMP (psv->pt3Angle.x),
483: MPFROM2SHORT (0, 359) );
484: WinSendDlgItemMsg (hwnd, IDD_ANGLE_Y, SBM_SETSCROLLBAR,
485: MPFROMP (psv->pt3Angle.y),
486: MPFROM2SHORT (0, 359) );
487: WinSendDlgItemMsg (hwnd, IDD_ANGLE_Z, SBM_SETSCROLLBAR,
488: MPFROMP (psv->pt3Angle.z),
489: MPFROM2SHORT (0, 359) );
490:
491: /* Set angular velocity ranges from 0 to 30 */
492:
493: WinSendDlgItemMsg (hwnd, IDD_ANGVEL_X, SBM_SETSCROLLBAR,
494: MPFROMP (psv->pt3AngVel.x),
495: MPFROM2SHORT (0, 30) );
496: WinSendDlgItemMsg (hwnd, IDD_ANGVEL_Y, SBM_SETSCROLLBAR,
497: MPFROMP (psv->pt3AngVel.y),
498: MPFROM2SHORT (0, 30) );
499: WinSendDlgItemMsg (hwnd, IDD_ANGVEL_Z, SBM_SETSCROLLBAR,
500: MPFROMP (psv->pt3AngVel.z),
501: MPFROM2SHORT (0, 30) );
502: break;
503:
504: case WM_HSCROLL:
505: switch (SHORT1FROMMP (mp1) )
506: {
507: case IDD_ANGLE_X:
508: case IDD_ANGLE_Y:
509: case IDD_ANGLE_Z:
510: cLineSize = 1;
511: cPageSize = 30;
512: break;
513: case IDD_ANGVEL_X:
514: case IDD_ANGVEL_Y:
515: case IDD_ANGVEL_Z:
516: cLineSize = 1;
517: cPageSize = 6;
518: break;
519: }
520:
521: switch (SHORT2FROMMP (mp2) )
522: {
523: case SB_LINELEFT:
524: cAddToPos = -cLineSize;
525: break;
526: case SB_LINERIGHT:
527: cAddToPos = cLineSize;
528: break;
529: case SB_PAGELEFT:
530: cAddToPos = -cPageSize;
531: break;
532: case SB_PAGERIGHT:
533: cAddToPos = cPageSize;
534: break;
535: default:
536: cAddToPos = 0;
537: break;
538: }
539: if (SHORT2FROMMP (mp2) == SB_SLIDERPOSITION)
540: iNewPosition = SHORT1FROMMP (mp2);
541: else
542: iNewPosition =
543: (INT) WinSendDlgItemMsg (hwnd, SHORT1FROMMP (mp1),
544: SBM_QUERYPOS, 0L, 0L)
545: + cAddToPos;
546:
547: /* Update slider position */
548:
549: WinSendDlgItemMsg (hwnd, SHORT1FROMMP (mp1), SBM_SETPOS,
550: MPFROMP (iNewPosition), NULL);
551: break;
552:
553: case WM_COMMAND:
554: switch (SHORT1FROMMP (mp1) )
555: {
556: case DID_OK:
557: psv = rgpsv [0];
558:
559: /* Accept new angles */
560:
561: psv->pt3Angle.x = (INT) WinSendDlgItemMsg (hwnd,
562: IDD_ANGLE_X, SBM_QUERYPOS, 0L, 0L);
563: psv->pt3Angle.y = (INT) WinSendDlgItemMsg (hwnd,
564: IDD_ANGLE_Y, SBM_QUERYPOS, 0L, 0L);
565: psv->pt3Angle.z = (INT) WinSendDlgItemMsg (hwnd,
566: IDD_ANGLE_Z, SBM_QUERYPOS, 0L, 0L);
567:
568: /* Accept new angular velocities */
569:
570: psv->pt3AngVel.x = (INT) WinSendDlgItemMsg (hwnd,
571: IDD_ANGVEL_X, SBM_QUERYPOS, 0L, 0L);
572: psv->pt3AngVel.y = (INT) WinSendDlgItemMsg (hwnd,
573: IDD_ANGVEL_Y, SBM_QUERYPOS, 0L, 0L);
574: psv->pt3AngVel.z = (INT) WinSendDlgItemMsg (hwnd,
575: IDD_ANGVEL_Z, SBM_QUERYPOS, 0L, 0L);
576:
577: WinDismissDlg (hwnd, TRUE);
578: break;
579:
580: case DID_CANCEL:
581: WinDismissDlg (hwnd, FALSE);
582: break;
583:
584: default:
585: break;
586: }
587: break;
588:
589: default:
590: return WinDefDlgProc (hwnd, msg, mp1, mp2);
591: }
592: return FALSE;
593: }
594:
595:
596: /*
597: * ListDlgProc:
598: * - allows the user to switch to a new shape in the parent window
599: */
600:
601: MRESULT EXPENTRY ListDlgProc(
602: HWND hwnd,
603: USHORT msg,
604: MPARAM mp1,
605: MPARAM mp2 )
606: {
607: PSV psv;
608: INT iShape;
609: INT iItem;
610: SHAPE *pshape;
611:
612: switch (msg)
613: {
614: case WM_INITDLG:
615: WinSendDlgItemMsg (hwnd, IDD_NEWSHAPE, LM_DELETEALL, NULL, NULL);
616:
617: /* Fill list box with shape names */
618:
619: for (iShape = 0; iShape < shapeMax; iShape++)
620: {
621: iItem = (USHORT) WinSendDlgItemMsg (hwnd, IDD_NEWSHAPE,
622: LM_INSERTITEM,
623: MPFROM2SHORT (LIT_SORTASCENDING, 0),
624: MPFROMP (rgshape [iShape].szName));
625: WinSendDlgItemMsg (hwnd, IDD_NEWSHAPE, LM_SETITEMHANDLE,
626: MPFROMP (iItem),
627: MPFROMP (iShape));
628: }
629: break ;
630:
631: case WM_COMMAND:
632: switch (SHORT1FROMMP (mp1) )
633: {
634: case DID_OK:
635: iShape = (USHORT) WinSendDlgItemMsg (hwnd, IDD_NEWSHAPE,
636: LM_QUERYSELECTION, 0L, 0L);
637:
638: if (iShape >= 0 && iShape <= shapeMax)
639: {
640: /* set parent window to display chosen shape */
641:
642: ishapeParent = (USHORT) WinSendDlgItemMsg (hwnd,
643: IDD_NEWSHAPE,
644: LM_QUERYITEMHANDLE,
645: MPFROMP (iShape), NULL);
646: psv = rgpsv [0];
647: pshape = &rgshape [ishapeParent];
648: psv->iShape = ishapeParent;
649: psv->fShaded = FALSE;
650: psv->fClipping = (pshape->pobject->rgface != NULL);
651: psv->fVarySize = FALSE;
652: psv->fPerspective = TRUE;
653: psv->pt2LightAng.x = 0;
654: psv->pt2LightAng.y = 0;
655: psv->pt3Angle = pshape->pinit->pt3Angle;
656: psv->pt3AngVel = pshape->pinit->pt3AngVel;
657: psv->pt3SizeAng = pshape->pinit->pt3SizeAng;
658:
659: /* set scale of shape for size of parent window */
660:
661: ChangeScale (psv);
662: WinDismissDlg (hwnd, TRUE);
663: }
664: else
665: WinDismissDlg (hwnd, FALSE);
666: break;
667:
668: case DID_CANCEL:
669: WinDismissDlg (hwnd, FALSE);
670: break;
671:
672: default:
673: break;
674: }
675: break;
676:
677: default:
678: return WinDefDlgProc (hwnd, msg, mp1, mp2);
679: }
680: return FALSE;
681: }
682:
683:
684: /*
685: * ParentWndProc:
686: * - process menu requests
687: * - start and terminate child windows
688: * - handle painting and size changes
689: */
690:
691: MRESULT EXPENTRY ParentWndProc(
692: HWND hwnd,
693: USHORT msg,
694: MPARAM mp1,
695: MPARAM mp2 )
696: {
697: HPS hps;
698: HDC hdc;
699: PSV psv = rgpsv [0];
700: SIZEL sizel;
701: LONG xPelsPerMeter, yPelsPerMeter;
702: INT iChild;
703: static BOOL fChildDisabled = FALSE;
704: SHAPE *pshape;
705: BOOL enClipping, enVarySize, enLightSource, enShaded;
706: /* enable flags for menu items */
707:
708: switch (msg)
709: {
710: case WM_CREATE:
711: hdc = WinOpenWindowDC (hwnd);
712:
713: DevQueryCaps (hdc, CAPS_WIDTH, 1L, &cxScreen);
714: DevQueryCaps (hdc, CAPS_HEIGHT, 1L, &cyScreen);
715:
716: DevQueryCaps (hdc, CAPS_HORIZONTAL_RESOLUTION, 1L, &xPelsPerMeter);
717: DevQueryCaps (hdc, CAPS_VERTICAL_RESOLUTION, 1L, &yPelsPerMeter);
718: yPelAdjust = (INT) ((yPelsPerMeter << 10) / xPelsPerMeter);
719:
720: sizel.cx = sizel.cy = 0;
721: psv->hpsClient = GpiCreatePS (hab, hdc, &sizel,
722: PU_PELS | GPIT_MICRO | GPIA_ASSOC );
723:
724: GpiSetBackMix (psv->hpsClient, BM_OVERPAINT);
725: GpiSetMix (psv->hpsClient, FM_OVERPAINT);
726: GpiSetBackColor (psv->hpsClient, CLR_WHITE);
727: break;
728:
729: case WM_INITMENU:
730: switch (SHORT1FROMMP (mp1))
731: {
732: case IDM_OPTIONS:
733: pshape = &rgshape [ishapeParent];
734:
735: /* disable/enable menu items */
736:
737: enShaded = pshape->pobject->rgface != NULL;
738: enClipping = enShaded
739: && (pshape->pobject->rgline != NULL)
740: && !psv->fShaded;
741: enLightSource = psv->fShaded;
742: enVarySize = !psv->fShaded;
743:
744: WinSendMsg(hwndMenu, MM_SETITEMATTR,
745: MPFROM2SHORT (IDM_CLIPPING, TRUE),
746: MPFROM2SHORT (MIA_DISABLED, enClipping ?
747: 0 : MIA_DISABLED) );
748:
749: WinSendMsg(hwndMenu, MM_SETITEMATTR,
750: MPFROM2SHORT (IDM_VARYSIZE, TRUE),
751: MPFROM2SHORT (MIA_DISABLED, enVarySize ?
752: 0 : MIA_DISABLED) );
753:
754: WinSendMsg(hwndMenu, MM_SETITEMATTR,
755: MPFROM2SHORT (IDM_LIGHTSOURCE, TRUE),
756: MPFROM2SHORT (MIA_DISABLED, enLightSource ?
757: 0 : MIA_DISABLED) );
758:
759: WinSendMsg(hwndMenu, MM_SETITEMATTR,
760: MPFROM2SHORT (IDM_SHADED, TRUE),
761: MPFROM2SHORT (MIA_DISABLED, enShaded ?
762: 0 : MIA_DISABLED) );
763:
764: /* display check marks */
765:
766: WinSendMsg(hwndMenu, MM_SETITEMATTR,
767: MPFROM2SHORT (IDM_SHADED, TRUE),
768: MPFROM2SHORT (MIA_CHECKED,
769: psv->fShaded ? MIA_CHECKED : 0) );
770:
771: WinSendMsg(hwndMenu, MM_SETITEMATTR,
772: MPFROM2SHORT (IDM_CLIPPING, TRUE),
773: MPFROM2SHORT (MIA_CHECKED,
774: psv->fClipping ? MIA_CHECKED : 0) );
775:
776: WinSendMsg(hwndMenu, MM_SETITEMATTR,
777: MPFROM2SHORT (IDM_VARYSIZE, TRUE),
778: MPFROM2SHORT (MIA_CHECKED,
779: psv->fVarySize ? MIA_CHECKED : 0) );
780:
781: WinSendMsg(hwndMenu, MM_SETITEMATTR,
782: MPFROM2SHORT (IDM_PERSPECTIVE, TRUE),
783: MPFROM2SHORT (MIA_CHECKED,
784: psv->fPerspective ? MIA_CHECKED : 0) );
785: break;
786:
787: default:
788: break;
789: }
790: break;
791:
792: case WM_COMMAND:
793: switch (SHORT1FROMMP (mp1))
794: {
795: case IDM_LIST:
796: /* display list dialog box */
797:
798: WinDlgBox (HWND_DESKTOP, hwnd, ListDlgProc,
799: NULL, IDD_LIST, NULL);
800: break;
801:
802: case IDM_ROTATION:
803: /* display rotation dialog box */
804:
805: WinDlgBox (HWND_DESKTOP, hwnd, RotationDlgProc,
806: NULL, IDD_ROTATION, NULL);
807: break;
808:
809: case IDM_LIGHTSOURCE:
810: /* display light source dialog box */
811:
812: WinDlgBox (HWND_DESKTOP, hwnd, LightSourceDlgProc,
813: NULL, IDD_LIGHTSOURCE, NULL);
814: break;
815:
816: case IDM_SHADED:
817: /* toggle shaded */
818:
819: psv->fShaded = !psv->fShaded;
820: break;
821:
822: case IDM_CLIPPING:
823: /* toggle clipping */
824:
825: psv->fClipping = !psv->fClipping;
826: break;
827:
828: case IDM_VARYSIZE:
829: /* toggle vary size */
830:
831: psv->fVarySize = !psv->fVarySize;
832: break;
833:
834: case IDM_PERSPECTIVE:
835: /* toggle perspective */
836:
837: psv->fPerspective = !psv->fPerspective;
838: break;
839:
840: case IDM_ABOUT:
841: /* display about dialog box */
842:
843: WinDlgBox (HWND_DESKTOP, hwnd, AboutDlgProc,
844: NULL, IDD_ABOUT, NULL);
845: break;
846:
847: case IDM_CHILD:
848: /* create child window when space exists */
849:
850: iChild = iNextFreeChild ();
851: if (iChild != 0)
852: {
853: if (iChild > iMaxChild)
854: iMaxChild = iChild;
855: CreateChild (iChild);
856: }
857:
858: if (iNextFreeChild () == 0)
859: {
860: fChildDisabled = TRUE;
861: WinSendMsg(hwndMenu, MM_SETITEMATTR,
862: MPFROM2SHORT (IDM_CHILD, TRUE),
863: MPFROM2SHORT (MIA_DISABLED, MIA_DISABLED) );
864: }
865: break;
866:
867: case IDM_ARRANGE:
868: /* arrange the windows to fill the screen */
869:
870: ArrangeWindows ();
871: break;
872: }
873: /* window is now invalid */
874:
875: WinInvalidateRect (hwnd, NULL, FALSE);
876: break;
877:
878: case WM_END_CHILD:
879: /* destroy child window and associated variables */
880:
881: iChild = SHORT1FROMMP (mp1);
882: psv = rgpsv [iChild];
883:
884: if (iChild == iMaxChild)
885: iMaxChild--;
886: rgpsv [iChild] = NULL;
887:
888: GpiDestroyPS (psv->hpsClient);
889: WinDestroyWindow (psv->hwndFrame);
890: free (psv);
891:
892: if (fChildDisabled)
893: {
894: fChildDisabled = FALSE;
895: WinSendMsg(hwndMenu, MM_SETITEMATTR,
896: MPFROM2SHORT (IDM_CHILD, TRUE),
897: MPFROM2SHORT (MIA_DISABLED, 0) );
898: }
899: break;
900:
901: case WM_SIZE:
902: /* change the centre and scale of shape for new window size */
903:
904: psv->ptCentre.x = SHORT1FROMMP (mp2) / 2;
905: psv->ptCentre.y = SHORT2FROMMP (mp2) / 2;
906:
907: ChangeScale (psv);
908: break;
909:
910: case WM_PAINT:
911: hps = WinBeginPaint (psv->hwndClient, NULL, NULL);
912: GpiErase (hps);
913: if (psv->fShaded)
914: DrawAndFill (psv);
915: WinEndPaint (hps);
916:
917: psv->fErased = TRUE;
918: break;
919:
920: case WM_CLOSE:
921: /* set flag so that main loop is terminated */
922:
923: fCloseParent = TRUE;
924: return WinDefWindowProc (hwnd, msg, mp1, mp2);
925:
926: default:
927: return WinDefWindowProc (hwnd, msg, mp1, mp2);
928: }
929: return FALSE;
930: }
931:
932:
933: /*
934: * ChildWndProc:
935: * - generic child procedure (used for all child windows)
936: * - send message to parent upon termination
937: * - handle painting and size changes
938: */
939:
940: MRESULT EXPENTRY ChildWndProc(
941: HWND hwnd,
942: USHORT msg,
943: MPARAM mp1,
944: MPARAM mp2 )
945: {
946: HPS hps;
947: HDC hdc;
948: PSV psv;
949: SIZEL sizel;
950: INT iChild;
951:
952: switch (msg)
953: {
954: case WM_CREATE:
955: psv = rgpsv [iChildCreate];
956:
957: hdc = WinOpenWindowDC (hwnd);
958:
959: sizel.cx = sizel.cy = 0;
960: psv->hpsClient = GpiCreatePS (hab, hdc, &sizel,
961: PU_PELS | GPIT_MICRO | GPIA_ASSOC );
962:
963: GpiSetBackMix (psv->hpsClient, BM_OVERPAINT);
964: GpiSetMix (psv->hpsClient, FM_OVERPAINT);
965: GpiSetBackColor (psv->hpsClient, CLR_WHITE);
966: break;
967:
968: case WM_SIZE:
969: /* change the centre and scale of shape for new window size */
970:
971: iChild = iQueryChild (hwnd);
972: psv = rgpsv [iChild];
973:
974: psv->ptCentre.x = SHORT1FROMMP (mp2) / 2;
975: psv->ptCentre.y = SHORT2FROMMP (mp2) / 2;
976:
977: ChangeScale (psv);
978: break;
979:
980: case WM_PAINT:
981: iChild = iQueryChild (hwnd);
982: psv = rgpsv [iChild];
983:
984: hps = WinBeginPaint (psv->hwndClient, NULL, NULL);
985: GpiErase (hps);
986: if (psv->fShaded)
987: DrawAndFill (psv);
988: WinEndPaint (hps);
989:
990: psv->fErased = TRUE;
991: break;
992:
993: case WM_CLOSE:
994: iChild = iQueryChild (hwnd);
995:
996: /* send termination message to parent */
997:
998: WinPostMsg (rgpsv [0]->hwndClient, WM_END_CHILD,
999: MPFROMSHORT (iChild), 0L);
1000: break;
1001:
1002: default:
1003: return WinDefWindowProc (hwnd, msg, mp1, mp2);
1004: }
1005: return FALSE;
1006: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.