|
|
1.1 root 1: /************************************************************************\
2: *
3: * PROGRAM: Regions.c
4: *
5: * PURPOSE: To demonstrate the region APIs in Win32, namely:
6: *
7: * CombineRgn()
8: * CreateEllipticRgn()
9: * CreateEllipticRgnIndirect()
10: * CreatePolygonRgn()
11: * CreatePolyPolygonRgn()
12: * CreateRectRgn()
13: * FillRgn()
14: * #ifdef NOTIMPLEMENTED FrameRgn() #endif
15: * GetRgnBox()
16: * InvertRgn()
17: * OffsetRgn()
18: * PaintRgn()
19: * PtInRegion()
20: * RectInRegion()
21: * SetRectRgn()
22: *
23: * The EqualRgn() API is *not* called in this program.
24: *
25: * FUNCTIONS:
26: * WinMain() - initialization, create window, msg loop
27: * MainWndProc() - processes main window msgs
28: * AboutDlgProc() - processes About dialog box msgs
29: * RgnBoxDlgProc() - processes RgnBox dialog box msgs
30: * MyCreateRgn() - calls any one of Create*Rgn*() APIs
31: * MyCombineRgn() - calls CombineRgn() API
32: * TrackRect() - creates\draws\deletes a tracking rectangle
33: * (for use with RectInRegion menu item.)
34: * Reset() - enables\disables menu items, modifies
35: * global vars (rgnArray[], currRgn).
36: *
37: * COMMENTS: This program allows a user to create the different kinds
38: * of regions available in Win32, and to perform the various
39: * operations on them. All operations are immediately
40: * reflected on the screen. The order in which the regions
41: * are created determines the order in which they are drawn,
42: * as well as which operation affects which region(s); for
43: * example, the last region created will be drawn on top of
44: * the others, and the operations in "Options" menu will
45: * affect this region. When two regions are combined the
46: * second region will be destroyed.
47: *
48: \************************************************************************/
49:
50: #include <windows.h>
51: #include "regions.h"
52:
53:
54:
55: /************************************************************************\
56: *
57: * FUNCTION: WinMain (standard WinMain INPUTS/RETURNS)
58: *
59: * GLOBAL VARS: hInst - Handle of program instance
60: *
61: \************************************************************************/
62:
63: int APIENTRY WinMain (HANDLE hInstance, HANDLE hPrevInstance,
64: LPSTR lpCmdLine, int nCmdShow)
65: { HWND hWnd;
66: MSG msg;
67:
68: if (!hPrevInstance)
69: { PWNDCLASS pWndClass;
70:
71: pWndClass = (PWNDCLASS) LocalAlloc (LPTR, sizeof(WNDCLASS));
72: if(!pWndClass)
73: { MessageBox (NULL, "REGIONS: LocalAlloc() failed", NULL, MB_OK |
74: MB_ICONHAND);
75: return(FALSE);
76: }
77:
78: pWndClass->hCursor = LoadCursor (NULL, IDC_ARROW);
79: pWndClass->hIcon = LoadIcon(NULL, IDI_APPLICATION);
80: pWndClass->lpszMenuName = (LPSTR) "Menu";
81: pWndClass->lpszClassName = (LPSTR) "Main";
82: pWndClass->hbrBackground = GetStockObject (DKGRAY_BRUSH);
83: pWndClass->hInstance = hInstance;
84: pWndClass->style = NULL;
85: pWndClass->lpfnWndProc = (WNDPROC)MainWndProc;
86:
87: if (!RegisterClass (pWndClass))
88: { MessageBox (NULL, "REGIONS: RegisterClass() failed", NULL, MB_OK |
89: MB_ICONHAND);
90: return(FALSE);
91: }
92:
93: LocalFree (LocalHandle ((LPSTR)pWndClass));
94: }
95: hInst = hInstance;
96: hWnd = CreateWindow ("Main", "Regions API Sample",
97: WS_OVERLAPPED | WS_CAPTION |
98: WS_SYSMENU | WS_MINIMIZEBOX,
99: CW_USEDEFAULT, CW_USEDEFAULT,
100: 220, 280, NULL, NULL, hInstance, NULL);
101: if (!hWnd)
102: return (NULL);
103:
104: ShowWindow(hWnd, nCmdShow);
105: UpdateWindow(hWnd);
106:
107: while (GetMessage(&msg, NULL, NULL, NULL))
108: { TranslateMessage(&msg);
109: DispatchMessage(&msg);
110: }
111: return (msg.wParam);
112: UNREFERENCED_PARAMETER(lpCmdLine);
113: }
114:
115:
116:
117: /************************************************************************\
118: *
119: * FUNCTION: MainWndProc (standard window procedure INPUTS/RETURNS)
120: *
121: * GLOBAL VARS: hInst - Handle of program instance
122: * rgnArray - Array of RGNSTRUCTs describing regions user has
123: * created
124: * currRgn - Index (in rgnArray) of most recently created
125: * region. If -1 then no regions created. Otherwise,
126: * values range from 0 to MAXRGNSTRUCTS - 1.
127: * hMenu - Handle of main window's menu.
128: *
129: * LOCAL VARS: rect - Scratch rectangle used in various places.
130: * ptr - Pointer to a TRACKRECTSTRUCT (used for
131: * tracking rectangle).
132: * i - For-loop variable.
133: * hdc - Scratch HDC used in various places.
134: * lButtonFlag - Tells what to do when left mouse button goes
135: * down (eg. nothing, check point in region,
136: * check rect in region).
137: * bOffsetRgnFlag - A BOOL which tells whether to offset up
138: * and left or down and right.
139: *
140: \************************************************************************/
141:
142: LONG APIENTRY MainWndProc (HWND hWnd, UINT message, UINT wParam,
143: LONG lParam)
144: { static RECT rect;
145: static PTRACKRECTSTRUCT ptr;
146: static BOOL bOffsetRgnFlag = FALSE;
147: static WORD lButtonFlag = 0;
148: int i;
149: HDC hdc;
150:
151: switch (message)
152: { case WM_CREATE:
153: hMenu = GetMenu (hWnd);
154: currRgn = -1;
155: Reset (RESET_ALL);
156: break;
157:
158: case WM_COMMAND:
159: switch (LOWORD(wParam))
160: { case IDM_ERASE:
161: Reset (RESET_ALL);
162: InvalidateRect (hWnd, NULL, TRUE);
163: break;
164:
165: case IDM_OFFSETRGN:
166:
167: /**************************************************************\
168: * Offset rgnArray[currRgn].hrgn either down & right, or up &
169: * left (depending on bOffsetRgnFlag). Toggle bOffsetRgnFlag.
170: \**************************************************************/
171:
172: if (bOffsetRgnFlag)
173: OffsetRgn (rgnArray[currRgn].hrgn, 15, 10);
174: else
175: OffsetRgn (rgnArray[currRgn].hrgn, -15, -10);
176: bOffsetRgnFlag = ~bOffsetRgnFlag;
177: InvalidateRect (hWnd, NULL, TRUE);
178:
179: break;
180:
181: case IDM_INVERTRGN:
182: hdc = GetDC (hWnd);
183: InvertRgn (hdc, rgnArray[currRgn].hrgn);
184: ReleaseDC (hWnd, hdc);
185: break;
186:
187: #ifdef NOTIMPLEMENTED
188:
189: case IDM_FRAMERGN:
190: hdc = GetDC (hWnd);
191:
192: FrameRgn (hdc, rgnArray[currRgn].hrgn,
193: GetStockObject (WHITE_BRUSH), 2, 2);
194: ReleaseDC (hWnd, hdc);
195: break;
196: #endif
197:
198: case IDM_PTINRGN:
199:
200: /**************************************************************\
201: * Uncheck "RectInRgn" menu item, toggle "PtInRgn" menu item,
202: * toggle lButtonFlag
203: \**************************************************************/
204:
205: if (lButtonFlag == IDM_RECTINRGN)
206: CheckMenuItem (GetSubMenu (hMenu, 0), IDM_RECTINRGN,
207: MF_UNCHECKED | MF_BYCOMMAND);
208: if (lButtonFlag == IDM_PTINRGN) {
209: CheckMenuItem (GetSubMenu (hMenu, 0), IDM_PTINRGN,
210: MF_UNCHECKED | MF_BYCOMMAND);
211: lButtonFlag = 0;
212: }
213: else {
214: CheckMenuItem (GetSubMenu (hMenu, 0), IDM_PTINRGN,
215: MF_CHECKED | MF_BYCOMMAND);
216: lButtonFlag = IDM_PTINRGN;
217: }
218: break;
219:
220: case IDM_RECTINRGN:
221:
222: /**************************************************************\
223: * Uncheck "PtInRgn" menu item, toggle "RectInRgn" menu item,
224: * toggle lButtonFlag
225: \**************************************************************/
226:
227: if (lButtonFlag == IDM_PTINRGN)
228: CheckMenuItem (GetSubMenu (hMenu, 0), IDM_PTINRGN,
229: MF_UNCHECKED | MF_BYCOMMAND);
230: if (lButtonFlag == IDM_RECTINRGN) {
231: CheckMenuItem (GetSubMenu (hMenu, 0), IDM_RECTINRGN,
232: MF_UNCHECKED | MF_BYCOMMAND);
233: lButtonFlag = 0;
234: }
235: else {
236: CheckMenuItem (GetSubMenu (hMenu, 0), IDM_RECTINRGN,
237: MF_CHECKED | MF_BYCOMMAND);
238: lButtonFlag = IDM_RECTINRGN;
239: }
240: break;
241:
242: case IDM_SETRECTRGN:
243:
244: /**************************************************************\
245: * Reset rgnArray[currRgn].hrgn to be the rectangle which
246: * currently bounds it.
247: \**************************************************************/
248:
249: GetRgnBox (rgnArray[currRgn].hrgn, &rect);
250: SetRectRgn (rgnArray[currRgn].hrgn, (int) rect.left,
251: (int) rect.top, (int) rect.right,
252: (int) rect.bottom);
253: InvalidateRect (hWnd, NULL, TRUE);
254: break;
255:
256: case IDM_GETRGNBOX: /* put up dlg which call GetRgnBox */
257: DialogBox (hInst, "RgnBox", hWnd, (DLGPROC)RgnBoxDlgProc);
258: break;
259:
260: case IDM_ELLIPSE: /* create an elliptic rgn */
261: MyCreateRgn (ELLIPTIC_RGN);
262: InvalidateRect (hWnd, NULL, TRUE);
263: break;
264:
265: case IDM_POLYPOLYGON: /* create a polyPolygon rgn */
266: MyCreateRgn (POLYPOLYGON_RGN);
267: InvalidateRect (hWnd, NULL, TRUE);
268: break;
269:
270: case IDM_RECT: /* create a rectangular rgn */
271: MyCreateRgn (RECT_RGN);
272: InvalidateRect (hWnd, NULL, TRUE);
273: break;
274:
275: case IDM_AND: /* combine previous 2 rgns */
276: MyCombineRgn (RGN_AND);
277: InvalidateRect (hWnd, NULL, TRUE);
278: break;
279:
280: case IDM_COPY: /* combine previous 2 rgns */
281: MyCombineRgn (RGN_COPY);
282: InvalidateRect (hWnd, NULL, TRUE);
283: break;
284:
285: case IDM_DIFF: /* combine previous 2 rgns */
286: MyCombineRgn (RGN_DIFF);
287: InvalidateRect (hWnd, NULL, TRUE);
288: break;
289:
290: case IDM_OR: /* combine previous 2 rgns */
291: MyCombineRgn (RGN_OR);
292: InvalidateRect (hWnd, NULL, TRUE);
293: break;
294:
295: case IDM_XOR: /* combine previous 2 rgns */
296: MyCombineRgn (RGN_XOR);
297: InvalidateRect (hWnd, NULL, TRUE);
298: break;
299:
300: case IDM_ABOUT: /* put up About dialog box */
301: DialogBox (hInst, "AboutBox", hWnd, (DLGPROC)AboutDlgProc);
302: break;
303: }
304: return (NULL);
305:
306: case WM_LBUTTONDOWN:
307: {
308: /******************************************************************\
309: * if the "PtInRgn" menu item is checked, then see if the point at
310: * which this event happened is within currRgn, MessageBeep if so.
311: *
312: * else if the "RectInRgn" menu items are checked, then start
313: * tracking rectangle mode
314: \******************************************************************/
315:
316: if (lButtonFlag == IDM_PTINRGN)
317: { if (currRgn > -1)
318: if (PtInRegion (rgnArray[currRgn].hrgn, (int) LOWORD(lParam),
319: (int) HIWORD(lParam)))
320: MessageBeep (0);
321: }
322: else if (lButtonFlag == IDM_RECTINRGN)
323: if ((ptr = TrackRect (NULL, TRECT_NEW, hWnd, lParam)) == NULL)
324:
325: /****************************************************************\
326: * If TrackRect failed to LocalAlloc, then disable the
327: * IDM_RECTINRGN opion.
328: \****************************************************************/
329:
330: EnableMenuItem (GetSubMenu (hMenu, 0), IDM_RECTINRGN,
331: MF_DISABLED | MF_GRAYED | MF_BYCOMMAND);
332:
333: return (NULL);
334: }
335: case WM_MOUSEMOVE:
336:
337: /******************************************************************\
338: * if in tracking rectangle mode call TrackRect
339: \******************************************************************/
340:
341: if (lButtonFlag == IDM_RECTINRGN && GetCapture () == hWnd)
342: TrackRect (ptr, TRECT_PAINT, hWnd, lParam);
343: return (NULL);
344:
345: case WM_LBUTTONUP:
346:
347: /******************************************************************\
348: * if in tracking rectangle mode call TrackRect, check out the final
349: * rectangle, and see if it intersects currRgn
350: \******************************************************************/
351:
352: if (lButtonFlag == IDM_RECTINRGN && GetCapture () == hWnd)
353: {
354: /****************************************************************\
355: * call TrackRect with TRECT_PAINT so it updates the rectangle
356: * for the last time, then again with TRECT_DELETE so it frees
357: * up the TRACKRECTSTRUCT it allocated
358: \****************************************************************/
359:
360: TrackRect (ptr, TRECT_PAINT, hWnd, lParam);
361: rect = ptr->trackRect;
362: TrackRect (ptr, TRECT_DELETE, hWnd, lParam);
363: if (RectInRegion (rgnArray[currRgn].hrgn, &rect))
364: MessageBeep (0);
365: }
366: return (NULL);
367:
368: case WM_PAINT: {
369: PAINTSTRUCT ps;
370: COLORREF crColor;
371: HBRUSH hBrush;
372:
373: hdc = BeginPaint (hWnd, &ps);
374:
375: /******************************************************************\
376: * For each rgn we created determine appropriate color & draw it
377: \******************************************************************/
378:
379: for (i = 0; i <= currRgn; i++)
380: { if (rgnArray[i].hrgn != NULL)
381: { crColor = 0x000000;
382: if (rgnArray[i].type & ELLIPTIC_RGN) /* add some red */
383: crColor |= 0x0000ff;
384: if (rgnArray[i].type & POLYPOLYGON_RGN) /* add some green */
385: crColor |= 0x00ff00;
386: if (rgnArray[i].type & RECT_RGN) /* add some blue */
387: crColor |= 0xff0000;
388: hBrush = CreateSolidBrush (crColor);
389:
390: /**************************************************************\
391: * Alternately, the following would work:
392: * SelectObject (hdc, hBrush);
393: * FillRgn (hdc, rgnArray[i].hrgn);
394: \**************************************************************/
395:
396: FillRgn (hdc, rgnArray[i].hrgn, hBrush);
397: DeleteObject (hBrush);
398: }
399: }
400: EndPaint (hWnd, &ps);
401: return (NULL);
402: }
403: case WM_DESTROY:
404:
405: PostQuitMessage(NULL);
406: return (NULL);
407: }
408: return (DefWindowProc(hWnd, message, wParam, lParam));
409: }
410:
411:
412:
413: /************************************************************************\
414: *
415: * FUNCTION: AboutDlgProc (standard dialog procedure INPUTS/RETURNS)
416: *
417: * COMMENTS: Displays "about" message
418: *
419: \************************************************************************/
420:
421: BOOL APIENTRY AboutDlgProc (HWND hDlg, UINT message, UINT wParam,
422: LONG lParam)
423: { switch (message)
424: { case WM_INITDIALOG:
425:
426: return (TRUE);
427:
428: case WM_COMMAND:
429:
430: if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL)
431: { EndDialog(hDlg, TRUE);
432: return (TRUE);
433: }
434: return (TRUE);
435: }
436: return (FALSE);
437: UNREFERENCED_PARAMETER(lParam);
438: }
439:
440:
441:
442: /************************************************************************\
443: *
444: * FUNCTION: RgnBoxDlgProc (standard dialog procedure INPUTS/RETURNS)
445: *
446: * GLOBAL VARS: rgnArray - Array of RGNSTRUCTs describing regions user has
447: * created
448: * currRgn - Index (in rgnArray) of most recently created
449: * region. If -1 then no regions created. Other-
450: * wise, values range from 0 to MAXRGNSTRUCTS - 1.
451: *
452: * COMMENTS: Displays bounding rectangle of most recently created
453: * region.
454: *
455: \************************************************************************/
456:
457: BOOL APIENTRY RgnBoxDlgProc (HWND hDlg, UINT message, UINT wParam,
458: LONG lParam)
459: {
460: switch (message)
461: { case WM_INITDIALOG:
462: { RECT rect;
463: char buf[15];
464:
465: /******************************************************************\
466: * get the bounding rect of currRgn, fill in the dlg controls
467: * with text string describing the bounding rect.
468: \******************************************************************/
469:
470: if (GetRgnBox (rgnArray[currRgn].hrgn, &rect) == SIMPLEREGION)
471: SetDlgItemText (hDlg, 102, "SIMPLEREGION");
472: else
473: SetDlgItemText (hDlg, 102, "COMPLEXREGION");
474:
475: wsprintf (buf, "%ld", rect.left);
476: SetDlgItemText (hDlg, 107, buf);
477: wsprintf (buf, "%ld", rect.top);
478: SetDlgItemText (hDlg, 108, buf);
479: wsprintf (buf, "%ld", rect.right);
480: SetDlgItemText (hDlg, 109, buf);
481: wsprintf (buf, "%ld", rect.bottom);
482: SetDlgItemText (hDlg, 110, buf);
483:
484: return (TRUE);
485: }
486: case WM_COMMAND:
487:
488: if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL)
489: { EndDialog(hDlg, TRUE);
490: return (TRUE);
491: }
492: return (TRUE);
493: }
494: return (FALSE);
495: UNREFERENCED_PARAMETER(lParam);
496: }
497:
498:
499:
500: /************************************************************************\
501: *
502: * FUNCTION: MyCreateRgn
503: *
504: * INPUTS: rgnStyle - The type of region to create (ELLIPTIC_RGN,
505: * POLYPOLYGON_RGN, RECT_RGN)
506: *
507: * GLOBAL VARS: rgnArray - Array of RGNSTRUCTs describing regions
508: * user has created.
509: * currRgn - Index (in rgnArray) of most recently
510: * created region. If -1 then no regions
511: * created. Otherwise, values range from
512: * 0 to MAXRGNSTRUCTS-1.
513: * hMenu - Handle of main window's menu.
514: * ellipseRect - Rectangle bounding elliptical region.
515: * polyPolygonPoints - The points for the polyPolygon region.
516: * polyPolygonCounts - The count of points for each polygon
517: * in the polyPolygon region.
518: * rectRect - The points for the rectangular region.
519: *
520: * COMMENTS: Creates a region (based on rgnStyle), increments currRgn,
521: * and fills in rgnArray[currRgn].
522: *
523: \************************************************************************/
524:
525: void MyCreateRgn (WORD rgnStyle)
526: { if (++currRgn == 0) /* if this is 1st rgn enable options menu */
527: Reset (ENABLE_OPTIONS);
528: else if (currRgn == 1) /* if this is 2nd rgn enable combine menu */
529: Reset (ENABLE_COMBINERGN);
530: rgnArray[currRgn].type = rgnStyle;
531:
532: switch (rgnStyle)
533: { case ELLIPTIC_RGN:
534:
535: /******************************************************************\
536: * The following will also work here:
537: * CreateEllipticRgn ((int) ellipseRect.left,
538: * (int) ellipseRect.top,
539: * (int) ellipseRect.right,
540: * (int) ellipseRect.bottom);
541: \******************************************************************/
542:
543: rgnArray[currRgn].hrgn = CreateEllipticRgnIndirect (&ellipseRect);
544:
545: EnableMenuItem (GetSubMenu (hMenu, 1), IDM_ELLIPSE,
546: MF_GRAYED | MF_DISABLED | MF_BYCOMMAND);
547: break;
548:
549: case POLYPOLYGON_RGN:
550:
551: /******************************************************************\
552: * Alternately, several calls to CreatePolygonRgn could be made.
553: \******************************************************************/
554:
555: rgnArray[currRgn].hrgn = CreatePolyPolygonRgn (polyPolygonPoints,
556: polyPolygonCounts,
557: POLYPOLYGONCOUNT,
558: WINDING);
559: EnableMenuItem (GetSubMenu (hMenu, 1), IDM_POLYPOLYGON,
560: MF_GRAYED | MF_DISABLED | MF_BYCOMMAND);
561: break;
562:
563: case RECT_RGN:
564:
565: /******************************************************************\
566: * Alternately, a call to CreatePolygonRgn could be made.
567: \******************************************************************/
568:
569: rgnArray[currRgn].hrgn = CreateRectRgn (rectRect.left,
570: rectRect.top,
571: rectRect.right,
572: rectRect.bottom);
573:
574: EnableMenuItem (GetSubMenu (hMenu, 1), IDM_RECT,
575: MF_GRAYED | MF_DISABLED | MF_BYCOMMAND);
576: break;
577: }
578: }
579:
580:
581:
582: /************************************************************************\
583: *
584: * FUNCTION: MyCombineRgn
585: *
586: * INPUTS: fnCombineMode- Operation to perform on the two regions
587: * (RGN_AND, RGN_COPY, RGN_DIFF, RGN_OR,
588: * RGN_XOR)
589: *
590: * GLOBAL VARS: rgnArray- Array of RGNSTRUCTs describing regions user has
591: * created
592: * currRgn - Index (in rgnArray) of most recently created
593: * region. If -1 then no regions created. Otherwise,
594: * values range from 0 to MAXRGNSTRUCTS - 1.
595: *
596: * COMMENTS: Combines the two regions rgnArray[currRgn-1] and
597: * rgnArray[currRgn] using fnCombineMode, placing the
598: * results in rgnArray[currRgn-1]. Destroys rgnArray[currRgn]
599: * and decrements currRgn.
600: *
601: \************************************************************************/
602:
603: void MyCombineRgn (int fnCombineMode)
604: {
605: if (currRgn >= 1) /* only if two or more regions have been created */
606: { CombineRgn (rgnArray[currRgn-1].hrgn, rgnArray[currRgn-1].hrgn,
607: rgnArray[currRgn].hrgn, fnCombineMode);
608:
609: rgnArray[currRgn-1].type |= rgnArray[currRgn].type;
610:
611: /* Delete the second of the two regions after combining */
612:
613: DeleteObject (rgnArray[currRgn--].hrgn);
614:
615: if (currRgn == 0)
616: Reset (DISABLE_COMBINERGN);
617: }
618: }
619:
620:
621:
622: /************************************************************************\
623: *
624: * FUNCTION: Reset
625: *
626: * INPUTS: action - Describes which reset action to take, eg. which
627: * menus to enable/disable etc...
628: *
629: * GLOBAL VARS: rgnArray - Array of RGNSTRUCTs describing regions user has
630: * created
631: * currRgn - Index (in rgnArray) of most recently created
632: * region. If -1 then no regions created. Other-
633: * wise, values range from 0 to MAXRGNSTRUCTS - 1.
634: * hMenu - Handle of main window's menu.
635: *
636: * COMMENTS: Sets appropriate menu states and deletes old regions
637: * according to "action" parameter.
638: *
639: \************************************************************************/
640:
641: void Reset (WORD action)
642: { UINT i;
643:
644: switch (action)
645: { case RESET_ALL:
646: if (currRgn > 0)
647: for (i = 0; i <= (UINT) currRgn; i++)
648: DeleteObject (rgnArray[i].hrgn);
649: currRgn = -1;
650: for (i = IDM_ERASE; i <= IDM_GETRGNBOX; i++)
651: EnableMenuItem (GetSubMenu (hMenu, 0), i, MF_DISABLED | MF_GRAYED
652: | MF_BYCOMMAND);
653: for (i = IDM_ELLIPSE; i <= IDM_RECT; i++)
654: EnableMenuItem (GetSubMenu (hMenu, 1), i, MF_ENABLED |
655: MF_BYCOMMAND);
656: for (i = IDM_AND; i <= IDM_XOR; i++)
657: EnableMenuItem (GetSubMenu (hMenu, 2), i, MF_DISABLED | MF_GRAYED
658: | MF_BYCOMMAND);
659: break;
660:
661: case ENABLE_OPTIONS:
662: for (i = IDM_ERASE; i <= IDM_GETRGNBOX; i++)
663: EnableMenuItem (GetSubMenu (hMenu, 0), i, MF_ENABLED |
664: MF_BYCOMMAND);
665: break;
666:
667: case ENABLE_COMBINERGN:
668: for (i = IDM_AND; i <= IDM_XOR; i++)
669: EnableMenuItem (GetSubMenu (hMenu, 2), i, MF_ENABLED |
670: MF_BYCOMMAND);
671: break;
672:
673: case DISABLE_COMBINERGN:
674: for (i = IDM_AND; i <= IDM_XOR; i++)
675: EnableMenuItem (GetSubMenu (hMenu, 2), i, MF_DISABLED | MF_GRAYED
676: | MF_BYCOMMAND);
677: break;
678: }
679: }
680:
681:
682: /************************************************************************\
683: *
684: * FUNCTION: TrackRect()
685: *
686: * INPUTS: ptr - Pointer to a PTRACKRECTSTRUCT.
687: * action - Message selecting what action to take.
688: * hWnd - Window handle for the window the track rect
689: * exists within.
690: * lParam - Fourth param to window proc (as with WM_MOUSEMOVE,
691: * WM_LBUTTONDOWN, WM_LBUTTONUP...) desribing
692: * event location.
693: *
694: * RETURNS: A pointer to a new TRACKRECTSTRUCT if msg == TRECT_NEW,
695: * NULL if msg != NEW
696: *
697: * COMMENTS: This function provides tracking rectangle functionality.
698: *
699: \************************************************************************/
700:
701: PTRACKRECTSTRUCT TrackRect (PTRACKRECTSTRUCT ptr, int action, HWND hWnd,
702: LONG lParam)
703: { if ((ptr == NULL) && (action != TRECT_NEW)) return NULL;
704:
705: switch (action)
706: {
707: /********************************************************************\
708: * TRECT_NEW: Allocate new PTRACKRECTSTRUCT. Fill in initial values
709: * for the fields of the structure. Set up the HDC
710: * correctly.
711: *
712: * return - pointer to the new object.
713: \********************************************************************/
714:
715: case TRECT_NEW:
716: { PTRACKRECTSTRUCT ptr;
717:
718: if ((ptr = LocalAlloc (LPTR, sizeof (TRACKRECTSTRUCT))) == NULL)
719: { MessageBox (hWnd, "REGIONS: LocalAlloc() failed", "Err!",
720: MB_OK | MB_ICONEXCLAMATION);
721: return NULL;
722: }
723:
724: /* initialize the HDC and other fields. */
725: ptr->hdc = GetDC(hWnd);
726: SetROP2(ptr->hdc, R2_NOT);
727: SelectObject (ptr->hdc, GetStockObject (NULL_BRUSH));
728: SelectObject (ptr->hdc, CreatePen (PS_SOLID, 2,
729: (COLORREF) 0x01000009));
730:
731: /* initialize the size. */
732: ptr->trackRect.left = ptr->trackRect.right =
733: (LONG) (ptr->xOrigin = LOWORD (lParam));
734: ptr->trackRect.top = ptr->trackRect.bottom =
735: (LONG) (ptr->yOrigin = HIWORD (lParam));
736:
737: SetCapture (hWnd);
738: GetClientRect (hWnd, &(ptr->clientRect));
739: return (ptr);
740: }
741:
742: /********************************************************************\
743: * TRECT_DELETE: Free up the memory allocated for the tracking rect.
744: * Also, erase the last rectangle we drew.
745: \********************************************************************/
746:
747: case TRECT_DELETE:
748: Rectangle (ptr->hdc, (int) ptr->trackRect.left,
749: (int) ptr->trackRect.top,
750: (int) ptr->trackRect.right,
751: (int) ptr->trackRect.bottom);
752: ReleaseDC (hWnd, ptr->hdc);
753: LocalFree (LocalHandle ((LPSTR)ptr));
754: ReleaseCapture ();
755: return NULL;
756:
757: /********************************************************************\
758: * TRECT_PAINT: Draw the tracking rectangle (involves erasing last
759: * rectangle at old coordinates, and drawing new rect
760: * at new coordinates).
761: \********************************************************************/
762:
763: case TRECT_PAINT:
764:
765: /******************************************************************\
766: * Remove the last rectangle we painted by painting over it again
767: \******************************************************************/
768:
769: Rectangle (ptr->hdc, (int) ptr->trackRect.left,
770: (int) ptr->trackRect.top,
771: (int) ptr->trackRect.right,
772: (int) ptr->trackRect.bottom);
773:
774: /******************************************************************\
775: * We want to restrict our Rectangle() calls to paint within the
776: * client area, so do a bounds check on lParam and reset any
777: * values which fall outside the client area (eg. <1,
778: * >clientRect.left, >clientRect.top).
779: \******************************************************************/
780:
781: if ((SHORT)LOWORD(lParam) < 1)
782: lParam &= 0xffff0000;
783: else if (LOWORD(lParam) > (WORD) (ptr->clientRect.right- 1))
784: lParam = MAKELONG ((WORD) ptr->clientRect.right - 1,
785: HIWORD(lParam));
786:
787: if ((SHORT)HIWORD(lParam) < 1)
788: lParam &= 0x0000ffff;
789: else if (HIWORD(lParam) > (WORD) (ptr->clientRect.bottom - 1))
790: lParam = MAKELONG (LOWORD(lParam),
791: (WORD) ptr->clientRect.bottom - 1);
792:
793: ptr->trackRect.left = (LONG) (ptr->xOrigin > LOWORD(lParam)
794: ? LOWORD(lParam) : ptr->xOrigin);
795: ptr->trackRect.right = (LONG) (ptr->xOrigin > LOWORD(lParam)
796: ? ptr->xOrigin : LOWORD(lParam));
797: ptr->trackRect.top = (LONG) (ptr->yOrigin > HIWORD(lParam)
798: ? HIWORD(lParam) : ptr->yOrigin);
799: ptr->trackRect.bottom = (LONG) (ptr->yOrigin > HIWORD(lParam)
800: ? ptr->yOrigin : HIWORD(lParam));
801:
802: /******************************************************************\
803: * Redraw the tracking rectangle
804: \******************************************************************/
805:
806: Rectangle (ptr->hdc, (int) ptr->trackRect.left,
807: (int) ptr->trackRect.top,
808: (int) ptr->trackRect.right,
809: (int) ptr->trackRect.bottom);
810: return NULL;
811: }
812: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.