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

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

unix.superglobalmegacorp.com

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