展示截图(略大,4.24M):
Demo下载(需要1积分):http://download.csdn.net/detail/joneeky/7860555
这些把位图加载到内存DC上的代码需要重复使用,于是定义成宏:
- #define READY_CODE \
- CGditestDlg *pMainDlg = (CGditestDlg *)pParam; \
- CDC *pDC = pMainDlg->GetDC(); \
- CBitmap bmp; \
- if (1 == pMainDlg->m_counter) \
- { \
- bmp.LoadBitmap(IDB_BITMAP1); \
- pMainDlg->m_counter = 2; \
- } \
- else if (2 == pMainDlg->m_counter) \
- { \
- bmp.LoadBitmap(IDB_BITMAP2); \
- pMainDlg->m_counter = 3; \
- } \
- else \
- { \
- bmp.LoadBitmap(IDB_BITMAP3); \
- pMainDlg->m_counter = 1; \
- } \
- CDC dcMem; \
- dcMem.CreateCompatibleDC(pDC); \
- dcMem.SelectObject(&bmp); \
- BITMAP bm; \
- bmp.GetBitmap(&bm); \
- pMainDlg->Invalidate(); \
- EnumChildWindows(pMainDlg->GetSafeHwnd(), \
- EnumChildProc, 0L);
- #define CLEAN_CODE \
- dcMem.DeleteDC(); \
- bmp.DeleteObject(); \
- EnumChildWindows( \
- pMainDlg->GetSafeHwnd(),\
- EnumChildProc, 1L); \
- #define PI 3.14
- //弧度 = 2π * 角度 / 360
- #define RADIAN(degree) ((float)((2 * PI * degree) / 360))
- /*从上飞入*/
- UINT CGditestDlg::FlyIntoFromTop(LPVOID pParam)
- {
- READY_CODE
- for (int ySrc = bm.bmHeight; ySrc >= 0; ySrc -= 10)
- {
- pDC->BitBlt(0, 0, bm.bmWidth, bm.bmHeight, &dcMem, 0, ySrc, SRCCOPY);
- Sleep(1);
- }
- CLEAN_CODE
- return 0;
- }
- /*从左飞入*/
- UINT CGditestDlg::FlyIntoFromLeft(LPVOID pParam)
- {
- READY_CODE
- for (int xSrc = bm.bmWidth; xSrc >= 0; xSrc -= 10)
- {
- pDC->BitBlt(0, 0, bm.bmWidth, bm.bmHeight, &dcMem, xSrc, 0, SRCCOPY);
- Sleep(1);
- }
- CLEAN_CODE
- return 0;
- }
- /*从上展开*/
- UINT CGditestDlg::UnfoldFromTop(LPVOID pParam)
- {
- READY_CODE
- for (int htDes = 0; htDes <= bm.bmHeight; htDes += 10)
- {
- pDC->BitBlt(0, 0, bm.bmWidth, htDes, &dcMem, 0, 0, SRCCOPY);
- Sleep(1);
- }
- CLEAN_CODE
- return 0;
- }
- /*从左展开*/
- UINT CGditestDlg::UnfoldFromLeft(LPVOID pParam)
- {
- READY_CODE
- for (int wtDes = 0; wtDes <= bm.bmWidth; wtDes += 10)
- {
- pDC->BitBlt(0, 0, wtDes, bm.bmHeight, &dcMem, 0, 0, SRCCOPY);
- Sleep(1);
- }
- CLEAN_CODE
- return 0;
- }
- /*水平百叶窗*/
- UINT CGditestDlg::HorizontalWindow(LPVOID pParam)
- {
- READY_CODE
- int n = bm.bmHeight / 8;
- for (int htDes = 0; htDes <= n; htDes += 1)
- {
- for (int i = 0; i < 8; i++)
- {
- pDC->BitBlt(0, n * i, bm.bmWidth, htDes, &dcMem, 0, n * i, SRCCOPY);
- }
- Sleep(10);
- }
- CLEAN_CODE
- return 0;
- }
- /*垂直百叶窗*/
- UINT CGditestDlg::VerticalWindow(LPVOID pParam)
- {
- READY_CODE
- int n = bm.bmWidth / 8;
- for (int wtDes = 0; wtDes <= n; wtDes += 1)
- {
- for (int i = 0; i < 8; i++)
- {
- pDC->BitBlt(n * i, 0, wtDes, bm.bmHeight, &dcMem, n * i, 0, SRCCOPY);
- }
- Sleep(10);
- }
- CLEAN_CODE
- return 0;
- }
拉直其实和百叶窗相差不了多少,也是分块同步显示,但是每一块是慢慢变大的。
- /*往下拉直*/
- UINT CGditestDlg::StraightenToBottom(LPVOID pParam)
- {
- READY_CODE
- int n = bm.bmHeight / 8;
- for (int htDes = 0; htDes <= n; htDes += 1)
- {
- for (int i = 0; i < 8; i++)
- {
- pDC->BitBlt(0, htDes * i, bm.bmWidth, htDes, &dcMem, 0, n * i, SRCCOPY);
- }
- Sleep(10);
- }
- CLEAN_CODE
- return 0;
- }
- /*往右拉直*/
- UINT CGditestDlg::StraightenToRight(LPVOID pParam)
- {
- READY_CODE
- int n = bm.bmWidth / 8;
- for (int wtDes = 0; wtDes <= n; wtDes += 1)
- {
- for (int i = 0; i < 8; i++)
- {
- pDC->BitBlt(wtDes * i, 0, wtDes, bm.bmHeight, &dcMem, n * i, 0, SRCCOPY);
- }
- Sleep(10);
- }
- CLEAN_CODE
- return 0;
- }
- /*由小变大*/
- UINT CGditestDlg::SmallToLarge(LPVOID pParam)
- {
- READY_CODE
- float x, y, w, h;
- float base = 0;
- pDC->SetStretchBltMode(HALFTONE);
- while ((int)(base += 10) <= bm.bmWidth)
- {
- w = base;
- h = base * ((float)bm.bmHeight / (float)bm.bmWidth);
- x = (float)bm.bmWidth / 2 - w / 2;
- y = (float)bm.bmHeight / 2 - h / 2;
- pDC->StretchBlt((int)x, (int)y, (int)w, (int)h, &dcMem, 0, 0, bm.bmWidth, bm.bmHeight, SRCCOPY);
- Sleep(10);
- }
- CLEAN_CODE
- return 0;
- }
旋转变大比较复杂,在上网找到可以完成位图按任意弧度旋转的代码改了一下,使其可以指定显示的大小:
最后一个参数的颜色值,指定图像旋转后空出来的位置填充的颜色
- HBITMAP GetRotatedBitmap(HBITMAP hBitmap, float radians, int width, int height, COLORREF clrBack)
- {
- // Create a memory DC compatible with the display
- CDC sourceDC, destDC;
- sourceDC.CreateCompatibleDC( NULL );
- destDC.CreateCompatibleDC( NULL );
- // Get logical coordinates
- BITMAP bm, bmOld;
- ::GetObject( hBitmap, sizeof( bm ), &bm );
- bmOld = bm;
- bm.bmWidth = width;
- bm.bmHeight = height;
- float cosine = (float)cos(radians);
- float sine = (float)sin(radians);
- // Compute dimensions of the resulting bitmap
- // First get the coordinates of the 3 corners other than origin
- int x1 = (int)(bm.bmHeight * sine);
- int y1 = (int)(bm.bmHeight * cosine);
- int x2 = (int)(bm.bmWidth * cosine + bm.bmHeight * sine);
- int y2 = (int)(bm.bmHeight * cosine - bm.bmWidth * sine);
- int x3 = (int)(bm.bmWidth * cosine);
- int y3 = (int)(-bm.bmWidth * sine);
- int minx = min(0,min(x1, min(x2,x3)));
- int miny = min(0,min(y1, min(y2,y3)));
- int maxx = max(0,max(x1, max(x2,x3)));
- int maxy = max(0,max(y1, max(y2,y3)));
- int w = maxx - minx;
- int h = maxy - miny;
- // Create a bitmap to hold the result
- HBITMAP hbmResult = ::CreateCompatibleBitmap(CClientDC(NULL), w, h);
- HBITMAP hbmOldSource = (HBITMAP)::SelectObject( sourceDC.m_hDC, hBitmap );
- HBITMAP hbmOldDest = (HBITMAP)::SelectObject( destDC.m_hDC, hbmResult );
- // Draw the background color before we change mapping mode
- HBRUSH hbrBack = CreateSolidBrush( clrBack );
- HBRUSH hbrOld = (HBRUSH)::SelectObject( destDC.m_hDC, hbrBack );
- destDC.PatBlt( 0, 0, w, h, PATCOPY );
- ::DeleteObject( ::SelectObject( destDC.m_hDC, hbrOld ) );
- // We will use world transform to rotate the bitmap
- SetGraphicsMode(destDC.m_hDC, GM_ADVANCED);
- XFORM xform;
- xform.eM11 = cosine;
- xform.eM12 = -sine;
- xform.eM21 = sine;
- xform.eM22 = cosine;
- xform.eDx = (float)-minx;
- xform.eDy = (float)-miny;
- SetWorldTransform( destDC.m_hDC, &xform );
- // Now do the actual rotating - a pixel at a time
- // destDC.BitBlt(0,0,bm.bmWidth, bm.bmHeight, &sourceDC, 0, 0, SRCCOPY );
- destDC.SetStretchBltMode(HALFTONE);
- destDC.StretchBlt(0, 0, bm.bmWidth, bm.bmHeight, &sourceDC, 0, 0, bmOld.bmWidth, bmOld.bmHeight, SRCCOPY);
- // Restore DCs
- ::SelectObject( sourceDC.m_hDC, hbmOldSource );
- ::SelectObject( destDC.m_hDC, hbmOldDest );
- return hbmResult;
- }
还有就是我使用了双缓冲,怎么还闪烁得这么厉害我也不清楚了。
- /*旋转变大*/
- UINT CGditestDlg::LargerWithSpin(LPVOID pParam)
- {
- // READY_CODE
- CGditestDlg *pMainDlg = (CGditestDlg *)pParam;
- CDC *pDC = pMainDlg->GetDC();
- pMainDlg->Invalidate();
- EnumChildWindows(pMainDlg->GetSafeHwnd(), EnumChildProc, 0L);
- pDC->SetStretchBltMode(HALFTONE);
- CBitmap bmp;
- if (1 == pMainDlg->m_counter)
- {
- bmp.LoadBitmap(IDB_BITMAP1);
- pMainDlg->m_counter = 2;
- }
- else if (2 == pMainDlg->m_counter)
- {
- bmp.LoadBitmap(IDB_BITMAP2);
- pMainDlg->m_counter = 3;
- }
- else
- {
- bmp.LoadBitmap(IDB_BITMAP3);
- pMainDlg->m_counter = 1;
- }
- HBITMAP hBmp;
- CDC dcMem;
- CBitmap *pbmpRotated;
- BITMAP bm;
- int degree = 0;
- float width, height;
- float base = 0;
- long oldWidth, oldHeight;
- float x, y;
- int lastX = 0, lastY = 0, lastWidth = 0, lastHeight = 0;
- dcMem.CreateCompatibleDC(pDC);
- bmp.GetBitmap(&bm);
- oldWidth = bm.bmWidth;
- oldHeight = bm.bmHeight;
- CRect rcWnd;
- pMainDlg->GetWindowRect(&rcWnd);
- CBitmap bmpBkgd;
- CDC dcBkgd;
- dcBkgd.CreateCompatibleDC(pDC);
- bmpBkgd.CreateCompatibleBitmap(pDC, rcWnd.Width() + 200, rcWnd.Height() + 200);
- dcBkgd.SelectObject(&bmpBkgd);
- dcBkgd.FillSolidRect(0, 0, rcWnd.Width() + 200, rcWnd.Height() + 200, RGB(255, 174 ,201));
- while (1)
- {
- if (base <= oldWidth)
- {
- base += 15;
- }
- if (base > oldWidth && degree == 0)
- {
- break;
- }
- width = base;
- height = base * ((float)oldHeight / (float)oldWidth);
- hBmp = GetRotatedBitmap((HBITMAP)bmp.GetSafeHandle(), RADIAN(degree), (int)width, (int)height, RGB(255, 174 ,201));
- pbmpRotated = CBitmap::FromHandle(hBmp);
- dcMem.SelectObject(pbmpRotated);
- pbmpRotated->GetBitmap(&bm);
- x = (float)oldWidth / 2 - (float)bm.bmWidth / 2;
- y = (float)oldHeight / 2 - (float)bm.bmHeight / 2;
- pDC->BitBlt(lastX, lastY, lastWidth, lastHeight, &dcBkgd, 0, 0, SRCCOPY);
- pDC->BitBlt((int)x, (int)y, bm.bmWidth, bm.bmHeight, &dcMem, 0, 0, SRCCOPY);
- lastX = (int)x;
- lastY = (int)y;
- lastWidth = bm.bmWidth;
- lastHeight = bm.bmHeight;
- pbmpRotated->DeleteObject();
- degree = (degree += 15) > 360 ? 0 : degree;
- Sleep(1);
- }
- dcMem.DeleteDC();
- dcBkgd.DeleteDC();
- bmpBkgd.DeleteObject();
- EnumChildWindows(pMainDlg->GetSafeHwnd(), EnumChildProc, 1L);
- // CLEAN_CODE
- return 0;
- }