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