Annotation of q_a/samples/regions/regions.c, revision 1.1.1.1

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: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.