基于CWnd对话框,利用GDI+和PNG素材实现雪花飞舞唯美场景小程序。程序技术简单,仅供新手参考学习使用。
先看疗效:
下面来说说程序原理吧:
工程:VS,MFC(对话框)工程。
窗口:主窗口宽高为0,主要接收菜单传来的消息。绘图窗口宽高为屏幕的宽高,主要绘制雪花。
元素:雪花种类共12种,GDI+绘制不同的资源图片到窗口上。
动作:动作有3种,左移动、右移动、下移动。
动作原理:绘图窗口有一个定时器Timer,定时器根据时间来判断是否需要加入新的雪花图片,图片随机。
程绘图原理:
1.获取窗口DC。
2.创建位图、画刷。
3.随着TIMER,随机产生图像,同时定义好图像坐标与大小。
4.绘制图像到画刷中。
5.更新位图到窗口上。
用到的技术点:
窗口透明:
WS_EX_TOPMOST(顶层)
WS_EX_LAYERED(透明异形)
WS_EX_TRANSPARENT(消息穿透)
窗口绘图:
UpdateLayeredWindow();
GDI+:graphics.DrawImage、CDC 等。
托盘:Shell_NotifyIcon
菜单:TrackPopupMenu
关键代码与实现:
注册窗口类:
WNDCLASS wndcls;memset(&wndcls, 0, sizeof(WNDCLASS));wndcls.style = CS_DBLCLKS | CS_HREDRAW | CS_VREDRAW;wndcls.lpfnWndProc = ::DefWindowProc;wndcls.hInstance = AfxGetInstanceHandle();wndcls.hIcon = NULL;wndcls.hCursor = ::LoadCursor(NULL,IDC_ARROW);wndcls.hbrBackground = (HBRUSH)(COLOR_BTNFACE + 1);wndcls.lpszMenuName = NULL;wndcls.lpszClassName = lpszClassName;if(!AfxRegisterClass(&wndcls)){return FALSE;}
窗口透明异形:
int nWidth = GetSystemMetrics (SM_CXSCREEN);int nHeight = GetSystemMetrics (SM_CYSCREEN);DWORD dwExStyle = WS_EX_TOOLWINDOW | WS_EX_TOPMOST | WS_EX_LAYERED | WS_EX_TRANSPARENT;DWORD dwStyle = WS_POPUP | WS_VISIBLE | WS_SYSMENU;m_pSnowWnd = new CSnowWnd;BOOL bRes = m_pSnowWnd->CreateEx(dwExStyle, _T("CSnowWnd"), _T("Snow"), dwStyle, 0, 0, nWidth, nHeight, m_hWnd, NULL);m_pSnowWnd->ShowWindow(SW_SHOW);
创建画刷:
void CSnowWnd::MakeBkgndDC(){CDC *pDC = GetDC();CBitmap hBackground;hBackground.CreateCompatibleBitmap(pDC, m_rcWnd.Width(), m_rcWnd.Height());if(m_dcBack.m_hDC == NULL)m_dcBack.CreateCompatibleDC(pDC);CBitmap *pOldBmp = m_dcBack.SelectObject(&hBackground);pOldBmp->DeleteObject();hBackground.DeleteObject();ReleaseDC(pDC);}
雪花位置、大小、移动数据的产生:
void CSnowWnd::DownSnow(){DWORD dwRes = 0;for(int i = m_nImgCount - 1; i >= 0; i--){PIMG pImage = m_ImgDrawSto[i];pImage->Y+= pImage->nSpeed;//下移if(pImage->Y > m_rcWnd.Height())//超出{m_ImgDrawSto.RemoveAt(i);//移除delete pImage;continue;}if(dwRes == 0)dwRes = GetTickCount() - pImage->dwTickCount;//横向移动 if (pImage->Init){pImage->Init = FALSE;pImage->StepTpye = GetRand(1, 3);}switch (pImage->StepTpye){case 1:pImage->X--;break;case 2:pImage->X++;break;}}m_nImgCount = m_ImgDrawSto.GetCount();if(dwRes > 1800)//增加雪花时间控制AddSnow(GetRand(0, m_nRowMaxCount));DrawWnd();}
绘图:
void CSnowWnd::DrawWnd(){MakeBkgndDC();CDC * pDC = GetDC();Graphics g(m_dcBack.GetSafeHdc());for(int i=0;i<m_nImgCount;i++){PIMG pImage = m_ImgDrawSto[i];g.DrawImage(pImage->pImage, pImage->X, pImage->Y, pImage->Width, pImage->Height);}CPoint DestPt(0,0);CSize psize(m_rcWnd.Width(),m_rcWnd.Height());BLENDFUNCTION blend;blend.AlphaFormat = AC_SRC_ALPHA;blend.BlendFlags = 0;blend.BlendOp = AC_SRC_OVER;blend.SourceConstantAlpha = 255;UpdateLayeredWindow(pDC, NULL, &psize, &m_dcBack, &DestPt, 0, &blend, ULW_ALPHA);ReleaseDC(pDC);}
好了,主要的代码已经贴出来,如有疑问可以留言。
源程序下载链接:
/detail/xinsuiyishunjian/9587916