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

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

unix.superglobalmegacorp.com

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