--- mstools/samples/plgblt/plgblt.c 2018/08/09 18:20:39 1.1 +++ mstools/samples/plgblt/plgblt.c 2018/08/09 18:21:35 1.1.1.2 @@ -1,6 +1,11 @@ /**************************************************************************\ * plgblt.c -- sample program demonstrating the new PlgBlt() API. * +* Steve Firebaugh +* Microsoft Developer Support +* Copyright (c) 1992 Microsoft Corporation +* +* * design: There is one main window with one dialog box stretched to fill * the top of it. The parameters for the plgblt painted into the main * window are stored in the entry fields of this dialog box. The user @@ -25,6 +30,10 @@ HBITMAP hbmSrc, hbmMask = HANDLE hInst; HWND hwndMain, hwndDlg; +int nSpin; + + +#define BACKGROUNDBRUSH GetStockObject(LTGRAY_BRUSH) @@ -57,8 +66,8 @@ int APIENTRY WinMain(HINSTANCE hInstance wc.hInstance = hInstance; wc.hIcon = LoadIcon(hInstance, "plgbltIcon"); wc.hCursor = LoadCursor(NULL, IDC_ARROW); - wc.hbrBackground = GetStockObject(LTGRAY_BRUSH); - wc.lpszMenuName = NULL; + wc.hbrBackground = BACKGROUNDBRUSH; + wc.lpszMenuName = "plgbltMenu"; wc.lpszClassName = "plgblt"; if (!RegisterClass(&wc)) return (FALSE); @@ -96,6 +105,8 @@ int APIENTRY WinMain(HINSTANCE hInstance ShowWindow(hwndMain, nCmdShow); + /* get global handle to the menu */ + /* Load the accelerator table that provides clipboard support. */ haccel = LoadAccelerators (hInst, "bltAccel"); @@ -107,6 +118,10 @@ int APIENTRY WinMain(HINSTANCE hInstance if (!IsDialogMessage (hwndDlg, &msg)){ DispatchMessage(&msg); } + + /* if no messages, and we are spinning, then post spin message. */ + if (!PeekMessage (&msg, hwndMain, 0,0, PM_NOREMOVE) && nSpin) + PostMessage (hwndMain, WM_SPIN, 0,0); } /* Return the value from PostQuitMessage */ @@ -134,7 +149,7 @@ int APIENTRY WinMain(HINSTANCE hInstance * hdcDest, hdcSrc, hdcMask - HDCs for the 3 sub regions of the window. * hbmSrc, hbmMask - bitmap handles for source and mask. \**************************************************************************/ -LRESULT MainWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) +LRESULT CALLBACK MainWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) { static int miniWidth; static RECT rect; @@ -163,6 +178,14 @@ static HANDLE hPenGrid, hPenSeparator; hPenGrid = CreatePen (PS_SOLID, 1, GRIDCOLOR); hPenSeparator = CreatePen (PS_SOLID, 2*SEPARATORWIDTH, (COLORREF) 0x01000000); + + { HMENU hMenu; + hMenu = GetMenu (hwnd); + CheckMenuItem(hMenu, IDM_SPINTOPLEFT, MF_CHECKED); + CheckMenuItem(hMenu, IDM_SPINOFF , MF_CHECKED); + nSpin = FALSE; + } + break; @@ -393,13 +416,19 @@ static HANDLE hPenGrid, hPenSeparator; /**********************************************************************\ - * Accelerator & clipboard support. + * WM_SETFOCUS + * + * The main window should never have the focus. Set it back + * to the top dialog. + \**********************************************************************/ + case WM_SETFOCUS: SetFocus (hwndDlg); + return NULL; + + + + /**********************************************************************\ + * Menu item support. * - * Certain key strokes (c.f. *.rc) will cause the following WM_COMMAND - * messages. In response the app will copy a bitmap into the clipboard - * or paste down from it. In both cases, it is necessary to create a - * new bitmap since a bitmap in the clipboard belongs to the clipboard - * and not to the application. \**********************************************************************/ case WM_COMMAND: switch (LOWORD(wParam)) { @@ -407,12 +436,12 @@ static HANDLE hPenGrid, hPenSeparator; HDC hdcCompat; /******************************************************************\ - * WM_COMMAND, AID_COPY + * WM_COMMAND, IDM_COPY * * Create a new bitmap, copy the destination HDC bits into it, * and send the new bitmap to the clipboard. \******************************************************************/ - case AID_COPY: { + case IDM_COPY: { int X[4],Y[4]; int nWidth, nHeight; int Xmin, Ymin, Xmax, Ymax; @@ -459,13 +488,13 @@ static HANDLE hPenGrid, hPenSeparator; /******************************************************************\ - * WM_COMMAND, AID_PASTE + * WM_COMMAND, IDM_PASTE * * Get bitmap handle from clipboard, create a new bitmap, draw * the clipboard bitmap into the new one, and store the new * handle in the global hbmSrc. \******************************************************************/ - case AID_PASTE: { + case IDM_PASTE: { HBITMAP hbm; BITMAP bm; @@ -493,23 +522,477 @@ static HANDLE hPenGrid, hPenSeparator; } break; /******************************************************************\ - * WM_COMMAND, AID_CYCLE + * WM_COMMAND, IDM_BOTH * * Post a COPY and PASTE command message to this window so that with * one key stroke the user can copy the DEST image into the clipboard, * paste it down into the SRC hdc and cause the blt. \******************************************************************/ - case AID_CYCLE: - PostMessage (hwnd, WM_COMMAND, MAKELONG (AID_COPY , 1), 0); - PostMessage (hwnd, WM_COMMAND, MAKELONG (AID_PASTE, 1), 0); + case IDM_BOTH: + + PostMessage (hwnd, WM_COMMAND, MAKELONG (IDM_COPY , 1), 0); + PostMessage (hwnd, WM_COMMAND, MAKELONG (IDM_PASTE, 1), 0); + break; + + + + /******************************************************************\ + * WM_COMMAND, IDM_MODE_* + * + * manage mutually exclusive menu. + * call SetStretchBltMode() for the global destination hdc. + \******************************************************************/ + case IDM_MODE_BLACKONWHITE: + { HMENU hMenu; + hMenu = GetMenu (hwnd); + + CheckMenuItem(hMenu, IDM_MODE_BLACKONWHITE, MF_CHECKED); + CheckMenuItem(hMenu, IDM_MODE_COLORONCOLOR, MF_UNCHECKED); + CheckMenuItem(hMenu, IDM_MODE_WHITEONBLACK, MF_UNCHECKED); + CheckMenuItem(hMenu, IDM_MODE_HALFTONE , MF_UNCHECKED); + + SetStretchBltMode (hdcDest,BLACKONWHITE); + SendMessage (hwndMain, WM_PLGBLT, 0,0); + + } return NULL; + + case IDM_MODE_COLORONCOLOR: + { HMENU hMenu; + hMenu = GetMenu (hwnd); + + CheckMenuItem(hMenu, IDM_MODE_BLACKONWHITE, MF_UNCHECKED); + CheckMenuItem(hMenu, IDM_MODE_COLORONCOLOR, MF_CHECKED); + CheckMenuItem(hMenu, IDM_MODE_WHITEONBLACK, MF_UNCHECKED); + CheckMenuItem(hMenu, IDM_MODE_HALFTONE , MF_UNCHECKED); + + SetStretchBltMode (hdcDest,COLORONCOLOR); + SendMessage (hwndMain, WM_PLGBLT, 0,0); + + } return NULL; + + case IDM_MODE_WHITEONBLACK: + { HMENU hMenu; + hMenu = GetMenu (hwnd); + + CheckMenuItem(hMenu, IDM_MODE_BLACKONWHITE, MF_UNCHECKED); + CheckMenuItem(hMenu, IDM_MODE_COLORONCOLOR, MF_UNCHECKED); + CheckMenuItem(hMenu, IDM_MODE_WHITEONBLACK, MF_CHECKED); + CheckMenuItem(hMenu, IDM_MODE_HALFTONE , MF_UNCHECKED); + + SetStretchBltMode (hdcDest,WHITEONBLACK); + SendMessage (hwndMain, WM_PLGBLT, 0,0); + + } return NULL; + + case IDM_MODE_HALFTONE : + { HMENU hMenu; + hMenu = GetMenu (hwnd); + + CheckMenuItem(hMenu, IDM_MODE_BLACKONWHITE, MF_UNCHECKED); + CheckMenuItem(hMenu, IDM_MODE_COLORONCOLOR, MF_UNCHECKED); + CheckMenuItem(hMenu, IDM_MODE_WHITEONBLACK, MF_UNCHECKED); + CheckMenuItem(hMenu, IDM_MODE_HALFTONE , MF_CHECKED); + + SetStretchBltMode (hdcDest,HALFTONE); + SendMessage (hwndMain, WM_PLGBLT, 0,0); + + } return NULL; + + + + + + /******************************************************************\ + * WM_COMMAND, IDM_SPIN* + * + * manage mutually exclusive menu. + * + \******************************************************************/ + case IDM_SPINOFF: + { HMENU hMenu; + hMenu = GetMenu (hwnd); + + CheckMenuItem(hMenu, IDM_SPINOFF, MF_CHECKED); + CheckMenuItem(hMenu, IDM_SPIN5 , MF_UNCHECKED); + CheckMenuItem(hMenu, IDM_SPIN10 , MF_UNCHECKED); + CheckMenuItem(hMenu, IDM_SPIN30 , MF_UNCHECKED); + CheckMenuItem(hMenu, IDM_SPIN60 , MF_UNCHECKED); + CheckMenuItem(hMenu, IDM_SPIN90 , MF_UNCHECKED); + + nSpin = FALSE; + SendMessage (hwndMain, WM_PLGBLT, 0,0); + + } return NULL; + + case IDM_SPIN5 : + { HMENU hMenu; + hMenu = GetMenu (hwnd); + + CheckMenuItem(hMenu, IDM_SPINOFF, MF_UNCHECKED); + CheckMenuItem(hMenu, IDM_SPIN5 , MF_CHECKED); + CheckMenuItem(hMenu, IDM_SPIN10 , MF_UNCHECKED); + CheckMenuItem(hMenu, IDM_SPIN30 , MF_UNCHECKED); + CheckMenuItem(hMenu, IDM_SPIN60 , MF_UNCHECKED); + CheckMenuItem(hMenu, IDM_SPIN90 , MF_UNCHECKED); + + nSpin = 5; + + } return NULL; + + case IDM_SPIN10: + { HMENU hMenu; + hMenu = GetMenu (hwnd); + + CheckMenuItem(hMenu, IDM_SPINOFF, MF_UNCHECKED); + CheckMenuItem(hMenu, IDM_SPIN5 , MF_UNCHECKED); + CheckMenuItem(hMenu, IDM_SPIN10 , MF_CHECKED); + CheckMenuItem(hMenu, IDM_SPIN30 , MF_UNCHECKED); + CheckMenuItem(hMenu, IDM_SPIN60 , MF_UNCHECKED); + CheckMenuItem(hMenu, IDM_SPIN90 , MF_UNCHECKED); + + nSpin = 10; + + } return NULL; + + case IDM_SPIN30: + { HMENU hMenu; + hMenu = GetMenu (hwnd); + + CheckMenuItem(hMenu, IDM_SPINOFF, MF_UNCHECKED); + CheckMenuItem(hMenu, IDM_SPIN5 , MF_UNCHECKED); + CheckMenuItem(hMenu, IDM_SPIN10 , MF_UNCHECKED); + CheckMenuItem(hMenu, IDM_SPIN30 , MF_CHECKED); + CheckMenuItem(hMenu, IDM_SPIN60 , MF_UNCHECKED); + CheckMenuItem(hMenu, IDM_SPIN90 , MF_UNCHECKED); + + nSpin = 30; + + } return NULL; + + case IDM_SPIN60: + { HMENU hMenu; + hMenu = GetMenu (hwnd); + + CheckMenuItem(hMenu, IDM_SPINOFF, MF_UNCHECKED); + CheckMenuItem(hMenu, IDM_SPIN5 , MF_UNCHECKED); + CheckMenuItem(hMenu, IDM_SPIN10 , MF_UNCHECKED); + CheckMenuItem(hMenu, IDM_SPIN30 , MF_UNCHECKED); + CheckMenuItem(hMenu, IDM_SPIN60 , MF_CHECKED); + CheckMenuItem(hMenu, IDM_SPIN90 , MF_UNCHECKED); + + nSpin = 60; + + } return NULL; + + case IDM_SPIN90: + { HMENU hMenu; + hMenu = GetMenu (hwnd); + + CheckMenuItem(hMenu, IDM_SPINOFF, MF_UNCHECKED); + CheckMenuItem(hMenu, IDM_SPIN5 , MF_UNCHECKED); + CheckMenuItem(hMenu, IDM_SPIN10 , MF_UNCHECKED); + CheckMenuItem(hMenu, IDM_SPIN30 , MF_UNCHECKED); + CheckMenuItem(hMenu, IDM_SPIN60 , MF_UNCHECKED); + CheckMenuItem(hMenu, IDM_SPIN90 , MF_CHECKED); + + nSpin = 90; + + } return NULL; + + + case IDM_FLIPONCE: + nSpin = 90; + SendMessage (hwndMain, WM_SPIN, 0,0); + nSpin = FALSE; + return NULL; + + + + case IDM_SPINTOPLEFT: + { HMENU hMenu; + hMenu = GetMenu (hwnd); + + CheckMenuItem(hMenu, IDM_SPINTOPLEFT, MF_CHECKED); + CheckMenuItem(hMenu, IDM_SPINCENTER , MF_UNCHECKED); + + } return NULL; + + case IDM_SPINCENTER: + { HMENU hMenu; + hMenu = GetMenu (hwnd); + + CheckMenuItem(hMenu, IDM_SPINTOPLEFT, MF_UNCHECKED); + CheckMenuItem(hMenu, IDM_SPINCENTER , MF_CHECKED); + + } return NULL; + + + /******************************************************************\ + * WM_COMMAND, DID_NEW* + * + * menu equivalents for buttons on top dialog. Just pass along + * WM_COMMAND messages to the dialog. + * + \******************************************************************/ + case DID_NEWSRC: + case DID_NEWMASK: + SendMessage (hwndDlg, message, wParam, lParam); + return NULL; + + + /******************************************************************\ + * WM_COMMAND, IDM_ABOUT + * + * manage mutually exclusive menu. + * + \******************************************************************/ + case IDM_ABOUT: + DialogBox (hInst, "aboutBox", hwnd, (DLGPROC)About); + return NULL; + + + + } /* end switch */ break; /* end wm_command */ + /******************************************************************\ + * WM_SPIN + * + * Set up a transform to modify the destination points. + * (Note that the transform in hdcDest remains the identity.) + * Loop through, reblitting to the transformed points. + * Erase behind the old bitmap by keeping track of the region uncovered. + * + \******************************************************************/ + case WM_SPIN: { + + XFORM x; + HDC hdc; + float M11, M12, M21, M22; + int nSteps, i; + + POINT pivot; + POINT lpPoint[3]; + POINT lpRgnErase[4], lpRgnBmp[4]; + HRGN hrgnErase, hrgnBmp; + HMENU hMenu; + int XSrc, YSrc, nWidth, nHeight, XMask, YMask; + BOOL success; + + /* validate the dialog on top with the parameters in it. */ + if (!IsWindow(hwndDlg)) return NULL; + + /* Grab points out of the dialog entry fields. */ + lpPoint[0].x = GetDlgItemInt(hwndDlg, DID_P1X, &success, TRUE); + lpPoint[0].y = GetDlgItemInt(hwndDlg, DID_P1Y, &success, TRUE); + lpPoint[1].x = GetDlgItemInt(hwndDlg, DID_P2X, &success, TRUE); + lpPoint[1].y = GetDlgItemInt(hwndDlg, DID_P2Y, &success, TRUE); + lpPoint[2].x = GetDlgItemInt(hwndDlg, DID_P3X, &success, TRUE); + lpPoint[2].y = GetDlgItemInt(hwndDlg, DID_P3Y, &success, TRUE); + XSrc = GetDlgItemInt(hwndDlg, DID_XSRC, &success, TRUE); + YSrc = GetDlgItemInt(hwndDlg, DID_YSRC, &success, TRUE); + nWidth = GetDlgItemInt(hwndDlg, DID_WIDTH, &success, TRUE); + nHeight = GetDlgItemInt(hwndDlg, DID_HEIGHT, &success, TRUE); + XMask = GetDlgItemInt(hwndDlg, DID_XMASK, &success, TRUE); + YMask = GetDlgItemInt(hwndDlg, DID_YMASK, &success, TRUE); + + + /* get an HDC we can use to play with transforms. */ + hdc = GetDC (hwnd); + + + + /* check menu check to pivot on top-left corner, or pivot on center. */ + hMenu = GetMenu (hwnd); + + if (GetMenuState(hMenu, IDM_SPINCENTER, MF_BYCOMMAND) & MF_CHECKED) { + pivot.x = (lpPoint[1].x +lpPoint[2].x)/2; + pivot.y = (lpPoint[1].y +lpPoint[2].y)/2; + } else { + pivot.x = lpPoint[0].x; + pivot.y = lpPoint[0].y; + } + /* nSpin contains values reflecting the number of degrees per step. + * fill in the number of steps required (360 / nSpin), and fill in + * the precomputed transformation matrices. + */ + switch (nSpin) { + + case 5: + nSteps = 72; + M11 = M22 = (float)0.9961946980917; + M12 = (float)-0.08715574274766; M21 = (float)0.08715574274766; + break; + case 10: + nSteps = 36; + M11 = M22 = (float)0.984808; + M12 = (float)-0.173648; M21 = (float)0.173648; + break; + case 30: + nSteps = 12; + M11 = M22 = (float)0.866025; + M12 = (float)-0.5 ; M21 = (float)0.5; + break; + case 60: + nSteps = 6; + M11 = M22 = (float)0.5 ; + M12 = (float)-0.866025; M21 = (float)0.866025; + break; + case 90: + nSteps = 4; + M11 = M22 = (float)0.0; + M12 = (float)-1.0 ; M21 = (float)1.0; + break; + default: + MessageBox (hwnd, "nSpin invalid.", "Internal app error.", MB_ICONHAND); + return NULL; + + } /* end switch nSpin */ + + + + + /* translate objects from pivot point to origin. */ + x.eM11 = (float)1.0; + x.eM12 = (float)0.0; + x.eM21 = (float)0.0; + x.eM22 = (float)1.0; + x.eDx = (float)-pivot.x; + x.eDy = (float)-pivot.y; + ModifyWorldTransform (hdc, &x, MWT_RIGHTMULTIPLY); + + /* rotate object about origin. */ + x.eM11 = M11; + x.eM12 = M12; + x.eM21 = M21; + x.eM22 = M22; + x.eDx = (float)0.0; + x.eDy = (float)0.0; + ModifyWorldTransform (hdc, &x, MWT_RIGHTMULTIPLY); + + /* translate objects back to pivot point. */ + x.eM11 = (float)1.0; + x.eM12 = (float)0.0; + x.eM21 = (float)0.0; + x.eM22 = (float)1.0; + x.eDx = (float)pivot.x; + x.eDy = (float)pivot.y; + ModifyWorldTransform (hdc, &x, MWT_RIGHTMULTIPLY); + + + + /* fill in initial region for erasure... the region containing bmp */ + lpRgnErase[0] = lpPoint[0]; + lpRgnErase[1] = lpPoint[1]; + lpRgnErase[3] = lpPoint[2]; + lpRgnErase[2].x = lpPoint[1].x - lpPoint[0].x; + lpRgnErase[2].x += lpPoint[2].x - lpPoint[0].x; + lpRgnErase[2].x += lpPoint[0].x; + lpRgnErase[2].y = lpPoint[1].y - lpPoint[0].y; + lpRgnErase[2].y += lpPoint[2].y - lpPoint[0].y; + lpRgnErase[2].y += lpPoint[0].y; + + + + /* loop through transforming the points on each step. */ + for (i= 0; i