|
|
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.