基于CWnd对话框,利用GDI+和PNG素材实现雪花飞舞唯美场景小程序。程序技术简单,仅供新手参考学习使用。
先看疗效:
下面来说说程序原理吧:
工程:VS2005,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);
}
好了,主要的代码已经贴出来,如有疑问可以留言。
源程序下载链接:
http://download.csdn.net/detail/xinsuiyishunjian/9587916