Annotation of mstools/samples/plgblt/plgblt.c, revision 1.1.1.2

1.1       root        1: /**************************************************************************\
                      2: *  plgblt.c -- sample program demonstrating the new PlgBlt() API.
                      3: *
1.1.1.2 ! root        4: *         Steve Firebaugh
        !             5: *         Microsoft Developer Support
        !             6: *         Copyright (c) 1992 Microsoft Corporation
        !             7: *
        !             8: *
1.1       root        9: *  design:  There is one main window with one dialog box stretched to fill
                     10: *   the top of it.  The parameters for the plgblt painted into the main
                     11: *   window are stored in the entry fields of this dialog box.  The user
                     12: *   may change these values and see the effect on the blt.
                     13: \**************************************************************************/
                     14: 
                     15: #include <windows.h>
                     16: #include <commdlg.h>
                     17: #include <math.h>
                     18: #include <stdio.h>
                     19: #include "plgblt.h"
                     20: #include "track.h"
                     21: #include "bitmap.h"
                     22: 
                     23: 
                     24: 
                     25: /* global variables. */
                     26: PTrackObject ptoDest, ptoSrc, ptoMask = NULL;
                     27: HDC          hdcDest, hdcSrc, hdcMask;
                     28: HBITMAP               hbmSrc, hbmMask = NULL;
                     29: 
                     30: HANDLE hInst;
                     31: HWND   hwndMain, hwndDlg;
                     32: 
1.1.1.2 ! root       33: int nSpin;
        !            34: 
        !            35: 
        !            36: #define  BACKGROUNDBRUSH GetStockObject(LTGRAY_BRUSH)
1.1       root       37: 
                     38: 
                     39: 
                     40: /**************************************************************************\
                     41: *
                     42: *  function:  WinMain()
                     43: *
                     44: *  input parameters:  c.f. generic sample
                     45: *
                     46: \**************************************************************************/
                     47: int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
                     48:                      LPSTR lpCmdLine, int nCmdShow)
                     49: {
                     50:     MSG   msg;
                     51:     RECT rect;
                     52:     HANDLE haccel;
                     53: 
                     54:     UNREFERENCED_PARAMETER( lpCmdLine );
                     55: 
                     56: 
                     57:     /* Check for previous instance.  If none, then register class. */
                     58:     if (!hPrevInstance) {
                     59:         WNDCLASS  wc;
                     60: 
                     61:         wc.style = NULL;
                     62:         wc.lpfnWndProc = (WNDPROC)MainWndProc;
                     63: 
                     64:         wc.cbClsExtra = 0;
                     65:         wc.cbWndExtra = 0;
                     66:         wc.hInstance = hInstance;
                     67:         wc.hIcon = LoadIcon(hInstance, "plgbltIcon");
                     68:         wc.hCursor = LoadCursor(NULL, IDC_ARROW);
1.1.1.2 ! root       69:         wc.hbrBackground = BACKGROUNDBRUSH;
        !            70:         wc.lpszMenuName =  "plgbltMenu";
1.1       root       71:         wc.lpszClassName = "plgblt";
                     72: 
                     73:         if (!RegisterClass(&wc)) return (FALSE);
                     74:     }  /* class registered o.k. */
                     75: 
                     76: 
                     77:     /* Create the main window.  Return false if CreateWindow() fails */
                     78:     hInst = hInstance;
                     79: 
                     80:     hwndMain = CreateWindow(
                     81:         "plgblt",
                     82:         "plgblt",
                     83:         WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN,
                     84:         CW_USEDEFAULT,
                     85:         CW_USEDEFAULT,
                     86:         CW_USEDEFAULT,
                     87:         CW_USEDEFAULT,
                     88:         NULL,
                     89:         NULL,
                     90:         hInstance,
                     91:         NULL);
                     92: 
                     93:     if (!hwndMain) return (FALSE);
                     94: 
                     95: 
                     96:     /* create the top dialog as a child of the main window. */
                     97:     hwndDlg = CreateDialog (hInst, "plgbltDlg", hwndMain, (DLGPROC)DlgProc);
                     98: 
                     99:     /* Send main window a WM_SIZE message so that it will size the top
                    100:      *  dialog correctly.
                    101:      */
                    102:     GetClientRect (hwndMain, &rect);
                    103:     SendMessage (hwndMain, WM_SIZE, 0, (rect.right - rect.left));
                    104:     ShowWindow (hwndDlg, SW_SHOW);
                    105:     ShowWindow(hwndMain, nCmdShow);
                    106: 
                    107: 
1.1.1.2 ! root      108:     /* get global handle to the menu */
        !           109: 
1.1       root      110:     /* Load the accelerator table that provides clipboard support. */
                    111:     haccel = LoadAccelerators (hInst, "bltAccel");
                    112: 
                    113: 
                    114: 
                    115:     /* Loop getting messages and dispatching them. */
                    116:     while (GetMessage(&msg,NULL, NULL, NULL)) {
                    117:       if (!TranslateAccelerator(hwndMain, haccel, &msg))
                    118:       if (!IsDialogMessage (hwndDlg, &msg)){
                    119:         DispatchMessage(&msg);
                    120:       }
1.1.1.2 ! root      121: 
        !           122:       /* if no messages, and we are spinning, then post spin message. */
        !           123:       if (!PeekMessage (&msg, hwndMain, 0,0, PM_NOREMOVE) && nSpin)
        !           124:         PostMessage (hwndMain, WM_SPIN, 0,0);
1.1       root      125:     }
                    126: 
                    127:     /* Return the value from PostQuitMessage */
                    128:     return (msg.wParam);
                    129: }
                    130: 
                    131: 
                    132: 
                    133: 
                    134: /**************************************************************************\
                    135: *
                    136: *  function:  MainWndProc()
                    137: *
                    138: *  input parameters:  normal window procedure parameters.
                    139: *
                    140: *  There are 6 different HDCs used for the main window (in addition to the
                    141: *   temporary one returned from BeginPaint).  There are two for each of the
                    142: *   three thirds of the window.  The first one contains the bitmap.  The
                    143: *   second one is for the track object and is stored in the TRACKOBJECT
                    144: *   structure.
                    145: *
                    146: *  global variables:
                    147: *   hwndDlg - dialog with entry fields containing parameters.
                    148: *   ptoDest, ptoSrc, ptoMask - pointers to the direct manipulation objects
                    149: *   hdcDest, hdcSrc, hdcMask - HDCs for the 3 sub regions of the window.
                    150: *   hbmSrc, hbmMask          - bitmap handles for source and mask.
                    151: \**************************************************************************/
1.1.1.2 ! root      152: LRESULT CALLBACK MainWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
1.1       root      153: {
                    154: static int miniWidth;
                    155: static RECT rect;
                    156: static HANDLE hPenGrid, hPenSeparator;
                    157: 
                    158:   switch (message) {
                    159: 
                    160:     /**********************************************************************\
                    161:     *  WM_CREATE
                    162:     *
                    163:     * Get three new HDCs, then create three new track objects.
                    164:     *  Each track object has different allowed tracking modes.
                    165:     *  Finally create two pens for drawing later on.
                    166:     \**********************************************************************/
                    167:     case WM_CREATE:
                    168:         hdcSrc  = GetDC (hwnd);
                    169:         hdcDest = GetDC (hwnd);
                    170:         hdcMask = GetDC (hwnd);
                    171: 
                    172:         ptoDest = doTrackObject (NULL, TROB_NEW, hwnd,NULL);
                    173:         ptoDest->allowedModes = TMALL;
                    174:         ptoSrc  = doTrackObject (NULL, TROB_NEW, hwnd,NULL);
                    175:         ptoSrc->allowedModes = TMMOVE | TMSIZEXY;
                    176:         ptoMask = doTrackObject (NULL, TROB_NEW, hwnd,NULL);
                    177:         ptoMask->allowedModes = TMMOVE;
                    178: 
                    179:         hPenGrid      = CreatePen (PS_SOLID, 1, GRIDCOLOR);
                    180:         hPenSeparator = CreatePen (PS_SOLID, 2*SEPARATORWIDTH, (COLORREF) 0x01000000);
1.1.1.2 ! root      181: 
        !           182:         { HMENU hMenu;
        !           183:         hMenu = GetMenu (hwnd);
        !           184:         CheckMenuItem(hMenu, IDM_SPINTOPLEFT, MF_CHECKED);
        !           185:         CheckMenuItem(hMenu, IDM_SPINOFF    , MF_CHECKED);
        !           186:         nSpin = FALSE;
        !           187:         }
        !           188: 
1.1       root      189:     break;
                    190: 
                    191: 
                    192:     /**********************************************************************\
                    193:     *  WM_DESTROY
                    194:     *
                    195:     * Complement of WM_CREATE.  Free up all of the HDCs, send all of the
                    196:     *  track objects their delete messages, delete the pens,
                    197:     *  then call PostQuitMessage.
                    198:     \**********************************************************************/
                    199:     case WM_DESTROY:
                    200:         ReleaseDC (hwnd, hdcSrc );
                    201:         ReleaseDC (hwnd, hdcDest);
                    202:         ReleaseDC (hwnd, hdcMask);
                    203:         doTrackObject (ptoDest, TROB_DELETE, hwnd,NULL);
                    204:         doTrackObject (ptoSrc , TROB_DELETE, hwnd,NULL);
                    205:         doTrackObject (ptoMask, TROB_DELETE, hwnd,NULL);
                    206: 
                    207:         DeleteObject(hPenGrid);
                    208:         DeleteObject(hPenSeparator);
                    209: 
                    210:         PostQuitMessage(0);
                    211:     break;
                    212: 
                    213: 
                    214: 
                    215:     /**********************************************************************\
                    216:     *  WM_SIZE
                    217:     *
                    218:     * Stretch the top dialog to fill the width of the main window.
                    219:     * Adjust the viewport origins of the 6 HDCs.
                    220:     * Set the clip regions of the 6 HDCs.
                    221:     \**********************************************************************/
                    222:     case WM_SIZE: {
                    223:         HRGN hrgn;
                    224: 
                    225:         SetWindowPos (hwndDlg, NULL, 0,0, LOWORD(lParam), DIALOGHEIGHT, NULL);
                    226: 
                    227:         GetClientRect (hwndMain, &rect);
                    228:         miniWidth = rect.right/3;
                    229: 
                    230:         SetViewportOrgEx (hdcDest,      0,           DIALOGHEIGHT, NULL);
                    231:         SetViewportOrgEx (ptoDest->hdc, 0,           DIALOGHEIGHT, NULL);
                    232:         SetViewportOrgEx (hdcSrc,       miniWidth,   DIALOGHEIGHT, NULL);
                    233:         SetViewportOrgEx (ptoSrc->hdc,  miniWidth,   DIALOGHEIGHT, NULL);
                    234:         SetViewportOrgEx (hdcMask,      2*miniWidth, DIALOGHEIGHT, NULL);
                    235:         SetViewportOrgEx (ptoMask->hdc, 2*miniWidth, DIALOGHEIGHT, NULL);
                    236: 
                    237:         ptoDest->rectClip.left    = 0;
                    238:         ptoDest->rectClip.top     = DIALOGHEIGHT;
                    239:         ptoDest->rectClip.right   = miniWidth-2*SEPARATORWIDTH;
                    240:         ptoDest->rectClip.bottom  = rect.bottom;
                    241:         hrgn = CreateRectRgnIndirect (&ptoDest->rectClip);
                    242:         SelectClipRgn (hdcDest,      hrgn);
                    243:         SelectClipRgn (ptoDest->hdc, hrgn);
                    244:         DeleteObject (hrgn);
                    245: 
                    246:         ptoSrc->rectClip.left    = miniWidth;
                    247:         ptoSrc->rectClip.top     = DIALOGHEIGHT;
                    248:         ptoSrc->rectClip.right   = 2*miniWidth-2*SEPARATORWIDTH;
                    249:         ptoSrc->rectClip.bottom  = rect.bottom;
                    250:         hrgn = CreateRectRgnIndirect (&ptoSrc->rectClip);
                    251:         SelectClipRgn (hdcSrc,       hrgn);
                    252:         SelectClipRgn (ptoSrc->hdc,  hrgn);
                    253:         DeleteObject (hrgn);
                    254: 
                    255:         ptoMask->rectClip.left    = 2*miniWidth;
                    256:         ptoMask->rectClip.top     = DIALOGHEIGHT;
                    257:         ptoMask->rectClip.right   = 3*miniWidth;
                    258:         ptoMask->rectClip.bottom  = rect.bottom;
                    259:         hrgn = CreateRectRgnIndirect (&ptoMask->rectClip);
                    260:         SelectClipRgn (hdcMask,      hrgn);
                    261:         SelectClipRgn (ptoMask->hdc, hrgn);
                    262:         DeleteObject (hrgn);
                    263: 
                    264:         SendMessage (hwndDlg, WM_PUTUPLPOINTS, (DWORD)hdcDest, (LONG)ptoDest);
                    265:         SendMessage (hwndDlg, WM_PUTUPSRCRECT, (DWORD)hdcSrc,  (LONG)ptoSrc);
                    266:         SendMessage (hwndDlg, WM_PUTUPMASKPT,  (DWORD)hdcMask, (LONG)ptoMask);
                    267: 
                    268:         /* repaint the whole window. */
                    269:         InvalidateRect (hwnd, NULL, TRUE);
                    270:     } break;
                    271: 
                    272: 
                    273: 
                    274:     /**********************************************************************\
                    275:     *  WM_PAINT
                    276:     *
                    277:     * miniWidth, rect -- set by WM_SIZE message.
                    278:     *
                    279:     * First shift the viewport origin down so that 0,0 is the top left
                    280:     *  most visible point (out from underneath the top dialog).  Second,
                    281:     *  draw the grid with wider lines on the axes.  Finally, read the
                    282:     *  values out of the top dialog, do elementary validation, and then
                    283:     *  try to call plgblt() with the values.
                    284:     \**********************************************************************/
                    285:      case WM_PAINT: {
                    286:         HDC hdc;
                    287:         PAINTSTRUCT ps;
                    288: 
                    289:         hdc = BeginPaint(hwnd, &ps);
                    290: 
                    291:         /* Draw Separator lines for the three miniareas */
                    292:         SelectObject(hdc, hPenSeparator);
                    293:         MoveToEx (hdc,   miniWidth-SEPARATORWIDTH,0, NULL);
                    294:         LineTo   (hdc,   miniWidth-SEPARATORWIDTH, rect.bottom);
                    295:         MoveToEx (hdc, 2*miniWidth-SEPARATORWIDTH,0, NULL);
                    296:         LineTo   (hdc, 2*miniWidth-SEPARATORWIDTH, rect.bottom);
                    297: 
                    298:         /* Grid the HDCs */
                    299:         SelectObject(hdcSrc, hPenGrid);
                    300:         DrawGrids (hdcSrc, miniWidth, rect.bottom);
                    301:         SelectObject(hdcMask, hPenGrid);
                    302:         DrawGrids (hdcMask, miniWidth, rect.bottom);
                    303: 
                    304:         /* Draw bitmaps if any, then draw track objects over them. */
                    305:         if (hbmSrc)  DrawBitmap (hdcSrc, hbmSrc);
                    306:         if (hbmMask) DrawBitmap (hdcMask, hbmMask);
                    307:         doTrackObject (ptoSrc , TROB_PAINT, hwnd, NULL);
                    308:         doTrackObject (ptoMask, TROB_PAINT, hwnd, NULL);
                    309: 
                    310:         /* paint the left third of the window. */
                    311:         SendMessage (hwnd, WM_PLGBLT, 0,0);
                    312: 
                    313:         EndPaint (hwnd, &ps);
                    314:     } return FALSE;
                    315: 
                    316: 
                    317: 
                    318:     /**********************************************************************\
                    319:     *  WM_PLGBLT
                    320:     *
                    321:     * WM_USER message.  This paints the left third of the window.  It
                    322:     *  is called on the WM_PAINT message.  It is separated out here because
                    323:     *  it is common for just the plgblt() to need to be called and not the
                    324:     *  whole window painted.
                    325:     \**********************************************************************/
                    326:     case WM_PLGBLT: {
                    327:         POINT lpPoint[3];
                    328:         int XSrc, YSrc, nWidth, nHeight, XMask, YMask;
                    329:         BOOL success;
                    330:         RECT cliprect;
                    331: 
                    332:         doTrackObject (ptoSrc , TROB_PAINT, hwnd, NULL);
                    333:         doTrackObject (ptoMask, TROB_PAINT, hwnd, NULL);
                    334: 
                    335:         GetClipBox (hdcDest, &cliprect);
                    336:         FillRect (hdcDest, &cliprect,
                    337:                   (HBRUSH) GetClassLong (hwnd, GCL_HBRBACKGROUND));
                    338:         SelectObject(hdcDest, hPenGrid);
                    339: 
                    340:         DrawGrids (hdcDest, miniWidth, rect.bottom);
                    341:         if (IsWindow(hwndDlg)) {
                    342: 
                    343:           /* Grab points out of the dialog entry fields. */
                    344:           lpPoint[0].x = GetDlgItemInt(hwndDlg, DID_P1X, &success, TRUE);
                    345:           lpPoint[0].y = GetDlgItemInt(hwndDlg, DID_P1Y, &success, TRUE);
                    346:           lpPoint[1].x = GetDlgItemInt(hwndDlg, DID_P2X, &success, TRUE);
                    347:           lpPoint[1].y = GetDlgItemInt(hwndDlg, DID_P2Y, &success, TRUE);
                    348:           lpPoint[2].x = GetDlgItemInt(hwndDlg, DID_P3X, &success, TRUE);
                    349:           lpPoint[2].y = GetDlgItemInt(hwndDlg, DID_P3Y, &success, TRUE);
                    350:           XSrc = GetDlgItemInt(hwndDlg, DID_XSRC, &success, TRUE);
                    351:           YSrc = GetDlgItemInt(hwndDlg, DID_YSRC, &success, TRUE);
                    352:           nWidth = GetDlgItemInt(hwndDlg, DID_WIDTH, &success, TRUE);
                    353:           nHeight = GetDlgItemInt(hwndDlg, DID_HEIGHT, &success, TRUE);
                    354:           XMask = GetDlgItemInt(hwndDlg, DID_XMASK, &success, TRUE);
                    355:           YMask = GetDlgItemInt(hwndDlg, DID_YMASK, &success, TRUE);
                    356: 
                    357: 
                    358:           /**********************************************************/
                    359:           /**********************************************************/
                    360:           PlgBlt (hdcDest, lpPoint,
                    361:                   hdcSrc, XSrc, YSrc, nWidth, nHeight,
                    362:                   hbmMask, XMask, YMask);
                    363:           /**********************************************************/
                    364:           /**********************************************************/
                    365:         }
                    366:         doTrackObject (ptoSrc , TROB_PAINT, hwnd, NULL);
                    367:         doTrackObject (ptoMask, TROB_PAINT, hwnd, NULL);
                    368:     } break;
                    369: 
                    370: 
                    371: 
                    372:     /**********************************************************************\
                    373:     *  WM_LBUTTONDOWN & WM_RBUTTONDOWN
                    374:     * On button down messages, hittest on the track object, and if
                    375:     *  it returns true, then send these messages to the track object.
                    376:     \**********************************************************************/
                    377:     case WM_RBUTTONDOWN:
                    378:     case WM_LBUTTONDOWN:
                    379:       if (doTrackObject(ptoDest, TROB_HITTEST, hwnd, lParam))
                    380:          doTrackObject(ptoDest, message, hwnd, lParam);
                    381:       else if (doTrackObject(ptoSrc, TROB_HITTEST, hwnd, lParam))
                    382:          doTrackObject(ptoSrc, message, hwnd, lParam);
                    383:       else if (doTrackObject(ptoMask, TROB_HITTEST, hwnd, lParam))
                    384:          doTrackObject(ptoMask, message, hwnd, lParam);
                    385:     break;
                    386: 
                    387: 
                    388: 
                    389:     /**********************************************************************\
                    390:     *  WM_LBUTTONUP & WM_RBUTTONDOWN & MW_MOUSEMOVE
                    391:     * If the track object is in a "tracking mode" then send it these messages.
                    392:     *  If the transform dialog is not minimized, fill it with numbers.
                    393:     *  If the mouse dialog is not minimized, fill it with numbers.
                    394:     \**********************************************************************/
                    395:     case WM_RBUTTONUP:
                    396:     case WM_LBUTTONUP:
                    397:       /* user action complete.  Force plgblt() update. */
                    398:       PostMessage (hwndMain, WM_PLGBLT, 0,0);
                    399:     case WM_MOUSEMOVE:
                    400:       if (ptoDest->Mode) {
                    401:         doTrackObject(ptoDest, message, hwnd, lParam);
                    402:         SendMessage (hwndDlg, WM_PUTUPLPOINTS, (DWORD) hdcDest, (LONG) ptoDest);
                    403:       }
                    404:       if (ptoSrc->Mode) {
                    405:         doTrackObject(ptoSrc, message, hwnd, lParam);
                    406:         SendMessage (hwndDlg, WM_PUTUPSRCRECT, (DWORD) hdcSrc, (LONG) ptoSrc);
                    407:       }
                    408: 
                    409:       if (ptoMask->Mode) {
                    410:         doTrackObject(ptoMask, message, hwnd, lParam);
                    411:         SendMessage (hwndDlg, WM_PUTUPMASKPT, (DWORD) hdcMask, (LONG) ptoMask);
                    412:       }
                    413: 
                    414:     break;
                    415: 
                    416: 
                    417: 
                    418:     /**********************************************************************\
1.1.1.2 ! root      419:     *  WM_SETFOCUS
        !           420:     *
        !           421:     * The main window should never have the focus.  Set it back
        !           422:     *  to the top dialog.
        !           423:     \**********************************************************************/
        !           424:     case WM_SETFOCUS: SetFocus (hwndDlg);
        !           425:         return NULL;
        !           426: 
        !           427: 
        !           428: 
        !           429:     /**********************************************************************\
        !           430:     *  Menu item support.
1.1       root      431:     *
                    432:     \**********************************************************************/
                    433:     case WM_COMMAND:
                    434:       switch (LOWORD(wParam)) {
                    435:         HBITMAP hbmCompat, hbmOld;
                    436:         HDC hdcCompat;
                    437: 
                    438:         /******************************************************************\
1.1.1.2 ! root      439:         *  WM_COMMAND, IDM_COPY
1.1       root      440:         *
                    441:         * Create a new bitmap, copy the destination HDC bits into it,
                    442:         *  and send the new bitmap to the clipboard.
                    443:         \******************************************************************/
1.1.1.2 ! root      444:         case IDM_COPY: {
1.1       root      445:           int X[4],Y[4];
                    446:           int nWidth, nHeight;
                    447:           int Xmin, Ymin, Xmax, Ymax;
                    448:           BOOL success;
                    449:           int i;
                    450: 
                    451:           for (i = 0; i<3 ; i++) {
                    452:             X[i] = GetDlgItemInt(hwndDlg, DID_P1X + 2*i, &success, TRUE);
                    453:             Y[i] = GetDlgItemInt(hwndDlg, DID_P1Y + 2*i, &success, TRUE);
                    454:           }
                    455: 
                    456:           X[3] = (X[1] - X[0]) + X[2];
                    457:           Y[3] = (Y[2] - Y[0]) + Y[1];
                    458: 
                    459:           Xmin = Xmax = X[0];
                    460:           Ymin = Ymax = Y[0];
                    461: 
                    462:           for (i = 1; i<4 ; i++) {
                    463:             Xmin = (X[i] < Xmin) ? X[i] : Xmin;
                    464:             Ymin = (Y[i] < Ymin) ? Y[i] : Ymin;
                    465:             Xmax = (X[i] > Xmax) ? X[i] : Xmax;
                    466:             Ymax = (Y[i] > Ymax) ? Y[i] : Ymax;
                    467:           }
                    468: 
                    469:           nWidth = Xmax - Xmin;
                    470:           nHeight = Ymax - Ymin;
                    471: 
                    472:           hdcCompat = CreateCompatibleDC(hdcDest);
                    473:           hbmCompat = CreateCompatibleBitmap (hdcDest, nWidth, nHeight);
                    474:           hbmOld = SelectObject(hdcCompat,hbmCompat);
                    475: 
                    476:           BitBlt (hdcCompat, 0,0,nWidth, nHeight, hdcDest, Xmin,Ymin, SRCCOPY );
                    477: 
                    478:           SelectObject(hdcCompat,hbmOld);
                    479:           DeleteDC(hdcCompat);
                    480: 
                    481:           OpenClipboard (hwnd);
                    482:           SetClipboardData (CF_BITMAP,hbmCompat);
                    483:           CloseClipboard ();
                    484: 
                    485:           DeleteObject (hbmCompat);
                    486: 
                    487:         } break;
                    488: 
                    489: 
                    490:         /******************************************************************\
1.1.1.2 ! root      491:         *  WM_COMMAND, IDM_PASTE
1.1       root      492:         *
                    493:         * Get bitmap handle from clipboard, create a new bitmap, draw
                    494:         *  the clipboard bitmap into the new one, and store the new
                    495:         *  handle in the global hbmSrc.
                    496:         \******************************************************************/
1.1.1.2 ! root      497:         case IDM_PASTE: {
1.1       root      498:           HBITMAP hbm;
                    499:           BITMAP bm;
                    500: 
                    501:           OpenClipboard (hwnd);
                    502:           if ( hbm = GetClipboardData (CF_BITMAP)) {
                    503:             DeleteObject (hbmSrc);
                    504: 
                    505:             GetObject (hbm, sizeof(BITMAP), &bm);
                    506: 
                    507:             hdcCompat = CreateCompatibleDC(hdcDest);
                    508:             hbmCompat = CreateCompatibleBitmap (hdcDest, bm.bmWidth, bm.bmHeight);
                    509:             hbmOld = SelectObject(hdcCompat,hbmCompat);
                    510: 
                    511:             DrawBitmap (hdcCompat, hbm);
                    512: 
                    513:             SelectObject(hdcCompat,hbmOld);
                    514:             DeleteDC(hdcCompat);
                    515: 
                    516:             hbmSrc = hbmCompat;
                    517: 
                    518:             InvalidateRect (hwnd, &ptoSrc->rectClip, TRUE);
                    519:             InvalidateRect (hwnd, &ptoDest->rectClip, TRUE);
                    520:           }
                    521:           CloseClipboard ();
                    522:         } break;
                    523: 
                    524:         /******************************************************************\
1.1.1.2 ! root      525:         *  WM_COMMAND, IDM_BOTH
1.1       root      526:         *
                    527:         * Post a COPY and PASTE command message to this window so that with
                    528:         *  one key stroke the user can copy the DEST image into the clipboard,
                    529:         *  paste it down into the SRC hdc and cause the blt.
                    530:         \******************************************************************/
1.1.1.2 ! root      531:         case IDM_BOTH:
        !           532: 
        !           533:           PostMessage (hwnd, WM_COMMAND, MAKELONG (IDM_COPY , 1), 0);
        !           534:           PostMessage (hwnd, WM_COMMAND, MAKELONG (IDM_PASTE, 1), 0);
        !           535: 
1.1       root      536:         break;
1.1.1.2 ! root      537: 
        !           538: 
        !           539: 
        !           540:         /******************************************************************\
        !           541:         *  WM_COMMAND, IDM_MODE_*
        !           542:         *
        !           543:         * manage mutually exclusive menu.
        !           544:         *  call SetStretchBltMode() for the global destination hdc.
        !           545:         \******************************************************************/
        !           546:         case IDM_MODE_BLACKONWHITE:
        !           547:           { HMENU hMenu;
        !           548:           hMenu = GetMenu (hwnd);
        !           549: 
        !           550:           CheckMenuItem(hMenu, IDM_MODE_BLACKONWHITE, MF_CHECKED);
        !           551:           CheckMenuItem(hMenu, IDM_MODE_COLORONCOLOR, MF_UNCHECKED);
        !           552:           CheckMenuItem(hMenu, IDM_MODE_WHITEONBLACK, MF_UNCHECKED);
        !           553:           CheckMenuItem(hMenu, IDM_MODE_HALFTONE    , MF_UNCHECKED);
        !           554: 
        !           555:           SetStretchBltMode (hdcDest,BLACKONWHITE);
        !           556:           SendMessage (hwndMain, WM_PLGBLT, 0,0);
        !           557: 
        !           558:           } return NULL;
        !           559: 
        !           560:         case IDM_MODE_COLORONCOLOR:
        !           561:           { HMENU hMenu;
        !           562:           hMenu = GetMenu (hwnd);
        !           563: 
        !           564:           CheckMenuItem(hMenu, IDM_MODE_BLACKONWHITE, MF_UNCHECKED);
        !           565:           CheckMenuItem(hMenu, IDM_MODE_COLORONCOLOR, MF_CHECKED);
        !           566:           CheckMenuItem(hMenu, IDM_MODE_WHITEONBLACK, MF_UNCHECKED);
        !           567:           CheckMenuItem(hMenu, IDM_MODE_HALFTONE    , MF_UNCHECKED);
        !           568: 
        !           569:           SetStretchBltMode (hdcDest,COLORONCOLOR);
        !           570:           SendMessage (hwndMain, WM_PLGBLT, 0,0);
        !           571: 
        !           572:           } return NULL;
        !           573: 
        !           574:         case IDM_MODE_WHITEONBLACK:
        !           575:           { HMENU hMenu;
        !           576:           hMenu = GetMenu (hwnd);
        !           577: 
        !           578:           CheckMenuItem(hMenu, IDM_MODE_BLACKONWHITE, MF_UNCHECKED);
        !           579:           CheckMenuItem(hMenu, IDM_MODE_COLORONCOLOR, MF_UNCHECKED);
        !           580:           CheckMenuItem(hMenu, IDM_MODE_WHITEONBLACK, MF_CHECKED);
        !           581:           CheckMenuItem(hMenu, IDM_MODE_HALFTONE    , MF_UNCHECKED);
        !           582: 
        !           583:           SetStretchBltMode (hdcDest,WHITEONBLACK);
        !           584:           SendMessage (hwndMain, WM_PLGBLT, 0,0);
        !           585: 
        !           586:           } return NULL;
        !           587: 
        !           588:         case IDM_MODE_HALFTONE    :
        !           589:           { HMENU hMenu;
        !           590:           hMenu = GetMenu (hwnd);
        !           591: 
        !           592:           CheckMenuItem(hMenu, IDM_MODE_BLACKONWHITE, MF_UNCHECKED);
        !           593:           CheckMenuItem(hMenu, IDM_MODE_COLORONCOLOR, MF_UNCHECKED);
        !           594:           CheckMenuItem(hMenu, IDM_MODE_WHITEONBLACK, MF_UNCHECKED);
        !           595:           CheckMenuItem(hMenu, IDM_MODE_HALFTONE    , MF_CHECKED);
        !           596: 
        !           597:           SetStretchBltMode (hdcDest,HALFTONE);
        !           598:           SendMessage (hwndMain, WM_PLGBLT, 0,0);
        !           599: 
        !           600:           } return NULL;
        !           601: 
        !           602: 
        !           603: 
        !           604: 
        !           605: 
        !           606:         /******************************************************************\
        !           607:         *  WM_COMMAND, IDM_SPIN*
        !           608:         *
        !           609:         * manage mutually exclusive menu.
        !           610:         *
        !           611:         \******************************************************************/
        !           612:         case IDM_SPINOFF:
        !           613:           { HMENU hMenu;
        !           614:           hMenu = GetMenu (hwnd);
        !           615: 
        !           616:           CheckMenuItem(hMenu, IDM_SPINOFF, MF_CHECKED);
        !           617:           CheckMenuItem(hMenu, IDM_SPIN5  , MF_UNCHECKED);
        !           618:           CheckMenuItem(hMenu, IDM_SPIN10 , MF_UNCHECKED);
        !           619:           CheckMenuItem(hMenu, IDM_SPIN30 , MF_UNCHECKED);
        !           620:           CheckMenuItem(hMenu, IDM_SPIN60 , MF_UNCHECKED);
        !           621:           CheckMenuItem(hMenu, IDM_SPIN90 , MF_UNCHECKED);
        !           622: 
        !           623:           nSpin = FALSE;
        !           624:           SendMessage (hwndMain, WM_PLGBLT, 0,0);
        !           625: 
        !           626:           } return NULL;
        !           627: 
        !           628:         case IDM_SPIN5 :
        !           629:           { HMENU hMenu;
        !           630:           hMenu = GetMenu (hwnd);
        !           631: 
        !           632:           CheckMenuItem(hMenu, IDM_SPINOFF, MF_UNCHECKED);
        !           633:           CheckMenuItem(hMenu, IDM_SPIN5  , MF_CHECKED);
        !           634:           CheckMenuItem(hMenu, IDM_SPIN10 , MF_UNCHECKED);
        !           635:           CheckMenuItem(hMenu, IDM_SPIN30 , MF_UNCHECKED);
        !           636:           CheckMenuItem(hMenu, IDM_SPIN60 , MF_UNCHECKED);
        !           637:           CheckMenuItem(hMenu, IDM_SPIN90 , MF_UNCHECKED);
        !           638: 
        !           639:           nSpin = 5;
        !           640: 
        !           641:           } return NULL;
        !           642: 
        !           643:         case IDM_SPIN10:
        !           644:           { HMENU hMenu;
        !           645:           hMenu = GetMenu (hwnd);
        !           646: 
        !           647:           CheckMenuItem(hMenu, IDM_SPINOFF, MF_UNCHECKED);
        !           648:           CheckMenuItem(hMenu, IDM_SPIN5  , MF_UNCHECKED);
        !           649:           CheckMenuItem(hMenu, IDM_SPIN10 , MF_CHECKED);
        !           650:           CheckMenuItem(hMenu, IDM_SPIN30 , MF_UNCHECKED);
        !           651:           CheckMenuItem(hMenu, IDM_SPIN60 , MF_UNCHECKED);
        !           652:           CheckMenuItem(hMenu, IDM_SPIN90 , MF_UNCHECKED);
        !           653: 
        !           654:           nSpin = 10;
        !           655: 
        !           656:           } return NULL;
        !           657: 
        !           658:         case IDM_SPIN30:
        !           659:           { HMENU hMenu;
        !           660:           hMenu = GetMenu (hwnd);
        !           661: 
        !           662:           CheckMenuItem(hMenu, IDM_SPINOFF, MF_UNCHECKED);
        !           663:           CheckMenuItem(hMenu, IDM_SPIN5  , MF_UNCHECKED);
        !           664:           CheckMenuItem(hMenu, IDM_SPIN10 , MF_UNCHECKED);
        !           665:           CheckMenuItem(hMenu, IDM_SPIN30 , MF_CHECKED);
        !           666:           CheckMenuItem(hMenu, IDM_SPIN60 , MF_UNCHECKED);
        !           667:           CheckMenuItem(hMenu, IDM_SPIN90 , MF_UNCHECKED);
        !           668: 
        !           669:           nSpin = 30;
        !           670: 
        !           671:           } return NULL;
        !           672: 
        !           673:         case IDM_SPIN60:
        !           674:           { HMENU hMenu;
        !           675:           hMenu = GetMenu (hwnd);
        !           676: 
        !           677:           CheckMenuItem(hMenu, IDM_SPINOFF, MF_UNCHECKED);
        !           678:           CheckMenuItem(hMenu, IDM_SPIN5  , MF_UNCHECKED);
        !           679:           CheckMenuItem(hMenu, IDM_SPIN10 , MF_UNCHECKED);
        !           680:           CheckMenuItem(hMenu, IDM_SPIN30 , MF_UNCHECKED);
        !           681:           CheckMenuItem(hMenu, IDM_SPIN60 , MF_CHECKED);
        !           682:           CheckMenuItem(hMenu, IDM_SPIN90 , MF_UNCHECKED);
        !           683: 
        !           684:           nSpin = 60;
        !           685: 
        !           686:           } return NULL;
        !           687: 
        !           688:         case IDM_SPIN90:
        !           689:           { HMENU hMenu;
        !           690:           hMenu = GetMenu (hwnd);
        !           691: 
        !           692:           CheckMenuItem(hMenu, IDM_SPINOFF, MF_UNCHECKED);
        !           693:           CheckMenuItem(hMenu, IDM_SPIN5  , MF_UNCHECKED);
        !           694:           CheckMenuItem(hMenu, IDM_SPIN10 , MF_UNCHECKED);
        !           695:           CheckMenuItem(hMenu, IDM_SPIN30 , MF_UNCHECKED);
        !           696:           CheckMenuItem(hMenu, IDM_SPIN60 , MF_UNCHECKED);
        !           697:           CheckMenuItem(hMenu, IDM_SPIN90 , MF_CHECKED);
        !           698: 
        !           699:           nSpin = 90;
        !           700: 
        !           701:           } return NULL;
        !           702: 
        !           703: 
        !           704:         case IDM_FLIPONCE:
        !           705:           nSpin = 90;
        !           706:           SendMessage (hwndMain, WM_SPIN, 0,0);
        !           707:           nSpin = FALSE;
        !           708:           return NULL;
        !           709: 
        !           710: 
        !           711: 
        !           712:         case IDM_SPINTOPLEFT:
        !           713:           { HMENU hMenu;
        !           714:           hMenu = GetMenu (hwnd);
        !           715: 
        !           716:           CheckMenuItem(hMenu, IDM_SPINTOPLEFT, MF_CHECKED);
        !           717:           CheckMenuItem(hMenu, IDM_SPINCENTER , MF_UNCHECKED);
        !           718: 
        !           719:           } return NULL;
        !           720: 
        !           721:         case IDM_SPINCENTER:
        !           722:           { HMENU hMenu;
        !           723:           hMenu = GetMenu (hwnd);
        !           724: 
        !           725:           CheckMenuItem(hMenu, IDM_SPINTOPLEFT, MF_UNCHECKED);
        !           726:           CheckMenuItem(hMenu, IDM_SPINCENTER , MF_CHECKED);
        !           727: 
        !           728:           } return NULL;
        !           729: 
        !           730: 
        !           731:         /******************************************************************\
        !           732:         *  WM_COMMAND, DID_NEW*
        !           733:         *
        !           734:         * menu equivalents for buttons on top dialog.  Just pass along
        !           735:         *  WM_COMMAND messages to the dialog.
        !           736:         *
        !           737:         \******************************************************************/
        !           738:         case DID_NEWSRC:
        !           739:         case DID_NEWMASK:
        !           740:           SendMessage (hwndDlg, message, wParam, lParam);
        !           741:         return NULL;
        !           742: 
        !           743: 
        !           744:         /******************************************************************\
        !           745:         *  WM_COMMAND, IDM_ABOUT
        !           746:         *
        !           747:         * manage mutually exclusive menu.
        !           748:         *
        !           749:         \******************************************************************/
        !           750:         case IDM_ABOUT:
        !           751:           DialogBox (hInst, "aboutBox", hwnd, (DLGPROC)About);
        !           752:         return NULL;
        !           753: 
        !           754: 
        !           755: 
        !           756: 
1.1       root      757:       }  /* end switch */
                    758: 
                    759:     break;  /* end wm_command */
                    760: 
                    761: 
                    762: 
1.1.1.2 ! root      763:     /******************************************************************\
        !           764:     *  WM_SPIN
        !           765:     *
        !           766:     * Set up a transform to modify the destination points.
        !           767:     *  (Note that the transform in hdcDest remains the identity.)
        !           768:     *  Loop through, reblitting to the transformed points.
        !           769:     *  Erase behind the old bitmap by keeping track of the region uncovered.
        !           770:     *
        !           771:     \******************************************************************/
        !           772:     case WM_SPIN: {
        !           773: 
        !           774:       XFORM  x;
        !           775:       HDC hdc;
        !           776:       float M11, M12, M21, M22;
        !           777:       int nSteps, i;
        !           778: 
        !           779:       POINT pivot;
        !           780:       POINT lpPoint[3];
        !           781:       POINT lpRgnErase[4], lpRgnBmp[4];
        !           782:       HRGN hrgnErase, hrgnBmp;
        !           783:       HMENU hMenu;
        !           784:       int XSrc, YSrc, nWidth, nHeight, XMask, YMask;
        !           785:       BOOL success;
        !           786: 
        !           787:       /* validate the dialog on top with the parameters in it. */
        !           788:       if (!IsWindow(hwndDlg)) return NULL;
        !           789: 
        !           790:       /* Grab points out of the dialog entry fields. */
        !           791:       lpPoint[0].x = GetDlgItemInt(hwndDlg, DID_P1X, &success, TRUE);
        !           792:       lpPoint[0].y = GetDlgItemInt(hwndDlg, DID_P1Y, &success, TRUE);
        !           793:       lpPoint[1].x = GetDlgItemInt(hwndDlg, DID_P2X, &success, TRUE);
        !           794:       lpPoint[1].y = GetDlgItemInt(hwndDlg, DID_P2Y, &success, TRUE);
        !           795:       lpPoint[2].x = GetDlgItemInt(hwndDlg, DID_P3X, &success, TRUE);
        !           796:       lpPoint[2].y = GetDlgItemInt(hwndDlg, DID_P3Y, &success, TRUE);
        !           797:       XSrc = GetDlgItemInt(hwndDlg, DID_XSRC, &success, TRUE);
        !           798:       YSrc = GetDlgItemInt(hwndDlg, DID_YSRC, &success, TRUE);
        !           799:       nWidth = GetDlgItemInt(hwndDlg, DID_WIDTH, &success, TRUE);
        !           800:       nHeight = GetDlgItemInt(hwndDlg, DID_HEIGHT, &success, TRUE);
        !           801:       XMask = GetDlgItemInt(hwndDlg, DID_XMASK, &success, TRUE);
        !           802:       YMask = GetDlgItemInt(hwndDlg, DID_YMASK, &success, TRUE);
        !           803: 
        !           804: 
        !           805:       /* get an HDC we can use to play with transforms. */
        !           806:       hdc = GetDC (hwnd);
        !           807: 
        !           808: 
        !           809: 
        !           810:       /* check menu check to pivot on top-left corner, or pivot on center. */
        !           811:       hMenu = GetMenu (hwnd);
        !           812: 
        !           813:       if (GetMenuState(hMenu, IDM_SPINCENTER, MF_BYCOMMAND) & MF_CHECKED) {
        !           814:         pivot.x = (lpPoint[1].x +lpPoint[2].x)/2;
        !           815:         pivot.y = (lpPoint[1].y +lpPoint[2].y)/2;
        !           816:       } else {
        !           817:         pivot.x = lpPoint[0].x;
        !           818:         pivot.y = lpPoint[0].y;
        !           819:       }
1.1       root      820: 
1.1.1.2 ! root      821:       /* nSpin contains values reflecting the number of degrees per step.
        !           822:        *  fill in the number of steps required (360 / nSpin), and fill in
        !           823:        *  the precomputed transformation matrices.
        !           824:        */
        !           825:       switch (nSpin) {
        !           826: 
        !           827:         case 5:
        !           828:           nSteps = 72;
        !           829:           M11 =                   M22 = (float)0.9961946980917;
        !           830:           M12 = (float)-0.08715574274766; M21 = (float)0.08715574274766;
        !           831:           break;
        !           832:         case 10:
        !           833:           nSteps = 36;
        !           834:           M11 =                   M22 = (float)0.984808;
        !           835:           M12 = (float)-0.173648; M21 = (float)0.173648;
        !           836:           break;
        !           837:         case 30:
        !           838:           nSteps = 12;
        !           839:           M11 =                   M22 = (float)0.866025;
        !           840:           M12 = (float)-0.5     ; M21 = (float)0.5;
        !           841:           break;
        !           842:         case 60:
        !           843:           nSteps = 6;
        !           844:           M11 =                   M22 = (float)0.5     ;
        !           845:           M12 = (float)-0.866025; M21 = (float)0.866025;
        !           846:           break;
        !           847:         case 90:
        !           848:           nSteps = 4;
        !           849:           M11 =                   M22 = (float)0.0;
        !           850:           M12 = (float)-1.0     ; M21 = (float)1.0;
        !           851:           break;
        !           852:         default:
        !           853:           MessageBox (hwnd, "nSpin invalid.", "Internal app error.", MB_ICONHAND);
        !           854:           return NULL;
        !           855: 
        !           856:       } /* end switch nSpin */
        !           857: 
        !           858: 
        !           859: 
        !           860: 
        !           861:       /* translate objects from pivot point to origin. */
        !           862:       x.eM11 = (float)1.0;
        !           863:       x.eM12 = (float)0.0;
        !           864:       x.eM21 = (float)0.0;
        !           865:       x.eM22 = (float)1.0;
        !           866:       x.eDx = (float)-pivot.x;
        !           867:       x.eDy = (float)-pivot.y;
        !           868:       ModifyWorldTransform (hdc, &x, MWT_RIGHTMULTIPLY);
        !           869: 
        !           870:       /* rotate object about origin. */
        !           871:       x.eM11 = M11;
        !           872:       x.eM12 = M12;
        !           873:       x.eM21 = M21;
        !           874:       x.eM22 = M22;
        !           875:       x.eDx = (float)0.0;
        !           876:       x.eDy = (float)0.0;
        !           877:       ModifyWorldTransform (hdc, &x, MWT_RIGHTMULTIPLY);
        !           878: 
        !           879:       /* translate objects back to pivot point. */
        !           880:       x.eM11 = (float)1.0;
        !           881:       x.eM12 = (float)0.0;
        !           882:       x.eM21 = (float)0.0;
        !           883:       x.eM22 = (float)1.0;
        !           884:       x.eDx = (float)pivot.x;
        !           885:       x.eDy = (float)pivot.y;
        !           886:       ModifyWorldTransform (hdc, &x, MWT_RIGHTMULTIPLY);
        !           887: 
        !           888: 
        !           889: 
        !           890:       /* fill in initial region for erasure... the region containing bmp */
        !           891:       lpRgnErase[0] = lpPoint[0];
        !           892:       lpRgnErase[1] = lpPoint[1];
        !           893:       lpRgnErase[3] = lpPoint[2];
        !           894:       lpRgnErase[2].x =  lpPoint[1].x - lpPoint[0].x;
        !           895:       lpRgnErase[2].x += lpPoint[2].x - lpPoint[0].x;
        !           896:       lpRgnErase[2].x += lpPoint[0].x;
        !           897:       lpRgnErase[2].y =  lpPoint[1].y - lpPoint[0].y;
        !           898:       lpRgnErase[2].y += lpPoint[2].y - lpPoint[0].y;
        !           899:       lpRgnErase[2].y += lpPoint[0].y;
        !           900: 
        !           901: 
        !           902: 
        !           903:       /* loop through transforming the points on each step. */
        !           904:       for (i= 0; i<nSteps; i++) {
        !           905: 
        !           906: 
        !           907:         hrgnErase = CreatePolygonRgn (lpRgnErase, 4, ALTERNATE);
        !           908: 
        !           909:         /* TRANSFORM the lpPoint[] destination extent points */
        !           910:         LPtoDP (hdc, lpPoint, 3);
        !           911: 
        !           912:         /* create a region containing the new bitmap extents */
        !           913:         lpRgnBmp[0] = lpPoint[0];
        !           914:         lpRgnBmp[1] = lpPoint[1];
        !           915:         lpRgnBmp[3] = lpPoint[2];
        !           916:         lpRgnBmp[2].x =  lpPoint[1].x - lpPoint[0].x;
        !           917:         lpRgnBmp[2].x += lpPoint[2].x - lpPoint[0].x;
        !           918:         lpRgnBmp[2].x += lpPoint[0].x;
        !           919:         lpRgnBmp[2].y =  lpPoint[1].y - lpPoint[0].y;
        !           920:         lpRgnBmp[2].y += lpPoint[2].y - lpPoint[0].y;
        !           921:         lpRgnBmp[2].y += lpPoint[0].y;
        !           922:         hrgnBmp = CreatePolygonRgn (lpRgnBmp, 4, ALTERNATE);
        !           923: 
        !           924:         /* subtract the new bitmap extents region from the erasure region. */
        !           925:         CombineRgn (hrgnErase, hrgnErase, hrgnBmp, RGN_DIFF);
        !           926: 
        !           927: 
        !           928: 
        !           929:         /* while we are here, get points ready for the next loop erasure */
        !           930:         lpRgnErase[0] = lpPoint[0];
        !           931:         lpRgnErase[1] = lpPoint[1];
        !           932:         lpRgnErase[3] = lpPoint[2];
        !           933:         lpRgnErase[2].x =  lpPoint[1].x - lpPoint[0].x;
        !           934:         lpRgnErase[2].x += lpPoint[2].x - lpPoint[0].x;
        !           935:         lpRgnErase[2].x += lpPoint[0].x;
        !           936:         lpRgnErase[2].y =  lpPoint[1].y - lpPoint[0].y;
        !           937:         lpRgnErase[2].y += lpPoint[2].y - lpPoint[0].y;
        !           938:         lpRgnErase[2].y += lpPoint[0].y;
        !           939: 
        !           940: 
        !           941: 
        !           942:         /**********************************************************/
        !           943:         PlgBlt (hdcDest, lpPoint,
        !           944:                 hdcSrc, XSrc, YSrc, nWidth, nHeight,
        !           945:                 hbmMask, XMask, YMask);
        !           946:         /**********************************************************/
        !           947: 
        !           948:         /* need to flush graphics buffer, or regions are erased
        !           949:          *  before the bitmap is drawn.
        !           950:          */
        !           951:         GdiFlush();
        !           952: 
        !           953:         /* erase the newly uncovered region. */
        !           954:         FillRgn (hdcDest, hrgnErase, BACKGROUNDBRUSH );
        !           955:         DeleteObject (hrgnErase);
        !           956:         DeleteObject (hrgnBmp);
        !           957:       } /* end for loop */
        !           958: 
        !           959: 
        !           960:       /* because of roundoff error, the 'nSteps'th rotation will not
        !           961:        *  always bring the parallelogram around to the 0th position.
        !           962:        *  So we special case the last position, and do one more erase.
        !           963:        *  Try commenting this out, and see the little glitches left
        !           964:        *  on the screen if this comment is unclear.
        !           965:        */
        !           966:       lpRgnErase[0] = lpPoint[0];
        !           967:       lpRgnErase[1] = lpPoint[1];
        !           968:       lpRgnErase[3] = lpPoint[2];
        !           969:       lpRgnErase[2].x =  lpPoint[1].x - lpPoint[0].x;
        !           970:       lpRgnErase[2].x += lpPoint[2].x - lpPoint[0].x;
        !           971:       lpRgnErase[2].x += lpPoint[0].x;
        !           972:       lpRgnErase[2].y =  lpPoint[1].y - lpPoint[0].y;
        !           973:       lpRgnErase[2].y += lpPoint[2].y - lpPoint[0].y;
        !           974:       lpRgnErase[2].y += lpPoint[0].y;
        !           975:       hrgnErase = CreatePolygonRgn (lpRgnErase, 4, ALTERNATE);
        !           976:       lpPoint[0].x = GetDlgItemInt(hwndDlg, DID_P1X, &success, TRUE);
        !           977:       lpPoint[0].y = GetDlgItemInt(hwndDlg, DID_P1Y, &success, TRUE);
        !           978:       lpPoint[1].x = GetDlgItemInt(hwndDlg, DID_P2X, &success, TRUE);
        !           979:       lpPoint[1].y = GetDlgItemInt(hwndDlg, DID_P2Y, &success, TRUE);
        !           980:       lpPoint[2].x = GetDlgItemInt(hwndDlg, DID_P3X, &success, TRUE);
        !           981:       lpPoint[2].y = GetDlgItemInt(hwndDlg, DID_P3Y, &success, TRUE);
        !           982:       lpRgnBmp[0] = lpPoint[0];
        !           983:       lpRgnBmp[1] = lpPoint[1];
        !           984:       lpRgnBmp[3] = lpPoint[2];
        !           985:       lpRgnBmp[2].x =  lpPoint[1].x - lpPoint[0].x;
        !           986:       lpRgnBmp[2].x += lpPoint[2].x - lpPoint[0].x;
        !           987:       lpRgnBmp[2].x += lpPoint[0].x;
        !           988:       lpRgnBmp[2].y =  lpPoint[1].y - lpPoint[0].y;
        !           989:       lpRgnBmp[2].y += lpPoint[2].y - lpPoint[0].y;
        !           990:       lpRgnBmp[2].y += lpPoint[0].y;
        !           991:       hrgnBmp = CreatePolygonRgn (lpRgnBmp, 4, ALTERNATE);
        !           992:       CombineRgn (hrgnErase, hrgnErase, hrgnBmp, RGN_DIFF);
        !           993:       FillRgn (hdcDest, hrgnErase, BACKGROUNDBRUSH );
        !           994:       DeleteObject (hrgnErase);
        !           995:       DeleteObject (hrgnBmp);
1.1       root      996: 
                    997: 
                    998: 
                    999: 
                   1000: 
                   1001: 
                   1002: 
1.1.1.2 ! root     1003:       ReleaseDC (hwnd, hdc);
        !          1004: 
        !          1005: 
        !          1006:     } return NULL; /* end WM_SPIN message */
1.1       root     1007: 
                   1008: 
                   1009: 
                   1010: 
                   1011:     default:
                   1012:       return (DefWindowProc(hwnd, message, wParam, lParam));
                   1013:     }
                   1014:     return (NULL);
                   1015: }
                   1016: 
                   1017: 
                   1018: 
                   1019: 
                   1020: /**************************************************************************\
                   1021: *
                   1022: *  function:  DlgProc()
                   1023: *
                   1024: *  input parameters:  normal window procedure parameters.
                   1025: *
                   1026: *  Respond to user button presses by getting new bitmaps or by sending
                   1027: *   the main window a WM_PLGBLT message.  Also handle special user messages
                   1028: *   for updating the entry fields with the contents of the direct manipulation
                   1029: *   objects.
                   1030: *
                   1031: *  global variables:
                   1032: *   hwndMain - the main window.  also the parent of this dialog
                   1033: *   ptoDest, ptoSrc, ptoMask - pointers to the direct manipulation objects
                   1034: *   hdcDest, hdcSrc, hdcMask - HDCs for the 3 sub regions of the window.
                   1035: *   hbmSrc, hbmMask          - bitmap handles for source and mask.
                   1036: \**************************************************************************/
1.1.1.2 ! root     1037: LRESULT CALLBACK DlgProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
1.1       root     1038: {
                   1039: 
                   1040:   switch (message) {
                   1041:     /**********************************************************************\
                   1042:     *  WM_INITDIALOG
                   1043:     *
                   1044:     * Fill the entry fields with sensible original values.
                   1045:     \**********************************************************************/
                   1046:     case WM_INITDIALOG:
                   1047:         SetDlgItemText(hwnd, DID_P1X     , "0");
                   1048:         SetDlgItemText(hwnd, DID_P1Y     , "0");
                   1049:         SetDlgItemText(hwnd, DID_P2X     , "0");
                   1050:         SetDlgItemText(hwnd, DID_P2Y     , "0");
                   1051:         SetDlgItemText(hwnd, DID_P3X     , "0");
                   1052:         SetDlgItemText(hwnd, DID_P3Y     , "0");
                   1053:         SetDlgItemText(hwnd, DID_XSRC    , "0");
                   1054:         SetDlgItemText(hwnd, DID_YSRC    , "0");
                   1055:         SetDlgItemText(hwnd, DID_WIDTH   , "0");
                   1056:         SetDlgItemText(hwnd, DID_HEIGHT  , "0");
                   1057:         SetDlgItemText(hwnd, DID_XMASK   , "0");
                   1058:         SetDlgItemText(hwnd, DID_YMASK   , "0");
                   1059:     return TRUE;
                   1060: 
                   1061: 
                   1062: 
                   1063:     /**********************************************************************\
                   1064:     *  WM_PUTUPLPOINTS
                   1065:     *
                   1066:     * wParam -  HDC with the needed world transform.
                   1067:     * lParam -  Pointer to the track object.
                   1068:     *
                   1069:     * Fill the entry fields for the array of 3 dest parallelogram points.
                   1070:     *  Conditionally change the first point depending on tracking mode.
                   1071:     \**********************************************************************/
                   1072:     case WM_PUTUPLPOINTS: {
                   1073:         POINT p, origin;
                   1074:         PTrackObject pto;
                   1075:         HDC hdc;
                   1076: 
                   1077:         hdc = (HDC) wParam;
                   1078:         pto = (PTrackObject) lParam;
                   1079:         GetViewportOrgEx (hdc, &origin);
                   1080: 
                   1081:         if (pto->Mode & TMMOVE) {
                   1082:           p.x = pto->rect.left;
                   1083:           p.y = pto->rect.top;
                   1084:           LPtoDP (pto->hdc, &p, 1);
                   1085:           p.x -= origin.x; p.y -= origin.y;
                   1086: 
                   1087:           SetDlgItemInt(hwnd, DID_P1X, p.x, TRUE);
                   1088:           SetDlgItemInt(hwnd, DID_P1Y, p.y, TRUE);
                   1089: 
                   1090:         }
                   1091: 
                   1092:         p.x = pto->rect.right;
                   1093:         p.y = pto->rect.top;
                   1094:         LPtoDP (pto->hdc, &p, 1);
                   1095:         p.x -= origin.x; p.y -= origin.y;
                   1096: 
                   1097:         SetDlgItemInt(hwnd, DID_P2X, p.x, TRUE);
                   1098:         SetDlgItemInt(hwnd, DID_P2Y, p.y, TRUE);
                   1099: 
                   1100:         p.x = pto->rect.left;
                   1101:         p.y = pto->rect.bottom;
                   1102:         LPtoDP (pto->hdc, &p, 1);
                   1103:         p.x -= origin.x; p.y -= origin.y;
                   1104:         SetDlgItemInt(hwnd, DID_P3X, p.x, TRUE);
                   1105:         SetDlgItemInt(hwnd, DID_P3Y, p.y, TRUE);
                   1106: 
                   1107:     } return FALSE;
                   1108: 
                   1109: 
                   1110: 
                   1111: 
                   1112:     /**********************************************************************\
                   1113:     *  WM_PUTUPSRCRECT
                   1114:     *
                   1115:     * wParam -  HDC with the needed world transform.
                   1116:     * lParam -  Pointer to the track object.
                   1117:     *
                   1118:     * Fill the entry fields for the source rectangle points.
                   1119:     *  Conditionally change <x,y> or <width,height> depending on tracking mode.
                   1120:     \**********************************************************************/
                   1121:     case WM_PUTUPSRCRECT: {
                   1122:         POINT p1,p2, origin;
                   1123:         PTrackObject pto;
                   1124:         HDC hdc;
                   1125: 
                   1126:         hdc = (HDC) wParam;
                   1127:         pto = (PTrackObject) lParam;
                   1128:         GetViewportOrgEx (hdc, &origin);
                   1129: 
                   1130:         p1.x = pto->rect.left;
                   1131:         p1.y = pto->rect.top;
                   1132:         LPtoDP (pto->hdc, &p1, 1);
                   1133: 
                   1134:         p2.x = pto->rect.right;
                   1135:         p2.y = pto->rect.bottom;
                   1136:         LPtoDP (pto->hdc, &p2, 1);
                   1137:         p2.x -= p1.x; p2.y -= p1.y;
                   1138: 
                   1139:         p1.x -= origin.x; p1.y -= origin.y;
                   1140: 
                   1141:         if (!(pto->Mode & TMSIZEXY)) {
                   1142:           SetDlgItemInt(hwnd, DID_XSRC, p1.x, TRUE);
                   1143:           SetDlgItemInt(hwnd, DID_YSRC, p1.y, TRUE);
                   1144:         }
                   1145: 
                   1146:         if (!(pto->Mode & TMMOVE)) {
                   1147:           SetDlgItemInt(hwnd, DID_WIDTH,  p2.x, TRUE);
                   1148:           SetDlgItemInt(hwnd, DID_HEIGHT, p2.y, TRUE);
                   1149:         }
                   1150:     } return FALSE;
                   1151: 
                   1152: 
                   1153: 
                   1154:     /**********************************************************************\
                   1155:     *  WM_PUTUPMASKPT
                   1156:     *
                   1157:     * wParam -  HDC with the needed world transform.
                   1158:     * lParam -  Pointer to the track object.
                   1159:     *
                   1160:     * Fill the entry fields for the mask location point.
                   1161:     \**********************************************************************/
                   1162:     case WM_PUTUPMASKPT: {
                   1163:         POINT p1, origin;
                   1164:         PTrackObject pto;
                   1165:         HDC hdc;
                   1166: 
                   1167:         hdc = (HDC) wParam;
                   1168:         pto = (PTrackObject) lParam;
                   1169:         GetViewportOrgEx (hdc, &origin);
                   1170: 
                   1171:         p1.x = pto->rect.left;
                   1172:         p1.y = pto->rect.top;
                   1173:         LPtoDP (pto->hdc, &p1, 1);
                   1174:         p1.x -= origin.x; p1.y -= origin.y;
                   1175: 
                   1176:         SetDlgItemInt(hwnd, DID_XMASK, p1.x, TRUE);
                   1177:         SetDlgItemInt(hwnd, DID_YMASK, p1.y, TRUE);
                   1178: 
                   1179:     } return FALSE;
                   1180: 
                   1181: 
                   1182: 
                   1183: 
                   1184:     /**********************************************************************\
                   1185:     *  WM_COMMAND, DID_DRAW
                   1186:     *
                   1187:     * Draw button hit - send main window message to call PlgBlt().
                   1188:     \**********************************************************************/
                   1189:     case WM_COMMAND: {
                   1190:       HBITMAP hbm;
                   1191: 
                   1192:       if (LOWORD(wParam) == DID_DRAW) {
                   1193:           SendMessage (hwndMain, WM_PLGBLT, 0,0);
                   1194: 
                   1195: 
                   1196:     /**********************************************************************\
                   1197:     *  WM_COMMAND, DID_NEWSRC
                   1198:     *
                   1199:     * Try to get a new source bitmap.  Then
                   1200:     *  invalidate two sub windows so that we force a repaint.
                   1201:     \**********************************************************************/
                   1202:       } else if (LOWORD(wParam) == DID_NEWSRC) {
                   1203:         if ( hbm = GetBitmap (hdcSrc, hInst, FALSE)) {
                   1204:           DeleteObject (hbmSrc);
                   1205:           hbmSrc = hbm;
                   1206:           InvalidateRect (hwndMain, &ptoSrc->rectClip, TRUE);
                   1207:           InvalidateRect (hwndMain, &ptoDest->rectClip, TRUE);
                   1208:         }
                   1209: 
                   1210:     /**********************************************************************\
                   1211:     *  WM_COMMAND, DID_Mask
                   1212:     *
                   1213:     * Try to get a new mask bitmap.  Then
                   1214:     *  invalidate two sub windows so that we force a repaint.
                   1215:     \**********************************************************************/
                   1216:       } else if (LOWORD(wParam) == DID_NEWMASK) {
                   1217:         if ( hbm = GetBitmap (hdcMask,  hInst, TRUE)) {
                   1218:           DeleteObject (hbmMask);
                   1219:           hbmMask = hbm;
                   1220:           InvalidateRect (hwndMain, &ptoMask->rectClip, TRUE);
                   1221:           InvalidateRect (hwndMain, &ptoDest->rectClip, TRUE);
                   1222:         }
                   1223:       }
                   1224: 
                   1225:     } return FALSE; /* end WM_COMMAND */
                   1226: 
                   1227: 
                   1228:     } /* end switch */
                   1229:     return (NULL);
                   1230: }
                   1231: 
                   1232: 
                   1233: 
                   1234: #define TICKSPACE     20
                   1235: 
                   1236: /**************************************************************************\
                   1237: *
                   1238: *  function:  DrawGrids()
                   1239: *
                   1240: *  input parameters:
                   1241: *   hdc - Device context to draw into.
                   1242: *   width, height - size of the rectangle to fill with grids.
                   1243: *
                   1244: *  global variables:  none.
                   1245: *
                   1246: \**************************************************************************/
                   1247: VOID DrawGrids (HDC hdc, int width, int height)
                   1248: {
                   1249: int i;
                   1250: 
                   1251:     /* Draw vertical lines. Double at the axis */
                   1252:     for (i = 0; i<= width; i+=TICKSPACE){
                   1253:       MoveToEx (hdc, i, 0, NULL);
                   1254:       LineTo (hdc, i, height);
                   1255:     }
                   1256:     MoveToEx (hdc, 1, 0, NULL);
                   1257:     LineTo (hdc, 1, height);
                   1258: 
                   1259:     /* Draw horizontal lines. Double at the axis */
                   1260:     for (i = 0; i<= height; i+=TICKSPACE){
                   1261:       MoveToEx (hdc, 0,i, NULL);
                   1262:       LineTo (hdc, width,i);
                   1263:     }
                   1264:     MoveToEx (hdc, 0, 1, NULL);
                   1265:     LineTo (hdc, width,1);
                   1266: 
                   1267:   return;
                   1268: }
1.1.1.2 ! root     1269: 
        !          1270: 
        !          1271: 
        !          1272: 
        !          1273: /****************************************************************************
        !          1274:     FUNCTION: About
        !          1275: ****************************************************************************/
        !          1276: LRESULT CALLBACK About(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
        !          1277: {
        !          1278:   if ((message == WM_COMMAND) && (LOWORD(wParam) == IDOK)) {
        !          1279:     EndDialog (hwnd, TRUE);
        !          1280:     return TRUE;
        !          1281:   }
        !          1282:   if ((message == WM_SYSCOMMAND) && (wParam == SC_CLOSE)) {
        !          1283:     EndDialog (hwnd, TRUE);
        !          1284:     return TRUE;
        !          1285:   }
        !          1286:   return FALSE;
        !          1287: }

unix.superglobalmegacorp.com

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