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