桌面上的飘雪!






4.91/5 (51投票s)
2006年12月20日
2分钟阅读

194321

3799
本文档解释了如何创建一个在桌面飘雪的应用程序。
引言
每当圣诞节到来时,我都会想为我的桌面制作一些有趣的玩具。
在互联网上搜索,很容易找到许多适用于任何场合(包括圣诞节)的精彩桌面礼物。不幸的是,我找不到任何此类桌面动画的源代码或开源示例。
因此,我决定创建自己的应用程序,让桌面上的其他窗口飘雪。正如我在互联网上看到的,许多作者使用不同的方法来显示桌面上的雪花飘落。我试图尽可能简单地创建我的应用程序,并决定开发一个系统托盘应用程序,其中包含许多子雪花窗口。我认为,这种方法最简单,但对于内存和视频使用方面有一些限制。
通用步骤
- 创建主窗口。
我们需要创建一个隐藏的框架窗口,并防止同时打开多个“Snow”窗口。以下代码片段展示了如何操作
BOOL CSnowApp::InitInstance() { HWND hWnd = ::FindWindow("SnowParentWindow","Snow"); if(hWnd) return FALSE; CMainFrame* pFrame = new CMainFrame; m_pMainWnd = pFrame; pFrame->LoadFrame(IDR_TRAYMENU, WS_OVERLAPPEDWINDOW, NULL, NULL); pFrame->ShowWindow(SW_HIDE); ... BOOL CMainFrame::PreCreateWindow(CREATESTRUCT& cs) { ... if(cs.hInstance) { static const TCHAR szClassName[] = _T("SnowParentWindow"); WNDCLASS wc; GetClassInfo(cs.hInstance, cs.lpszClass, &wc); wc.lpszClassName = szClassName; AfxRegisterClass(&wc); cs.lpszClass = szClassName; } ...
- 安装系统托盘图标。
int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct) { ... SetTrayIcon(NIM_ADD, m_hIcon, "Desktop Snow"); ... BOOL CMainFrame::SetTrayIcon(DWORD dwMessage, HICON hIcon, PSTR pszTip) { BOOL bResult = FALSE; NOTIFYICONDATA tnd; tnd.cbSize = sizeof(NOTIFYICONDATA); tnd.hWnd = m_hWnd; tnd.uID = NULL; tnd.uFlags = NIF_MESSAGE | NIF_ICON | NIF_TIP; tnd.uCallbackMessage = WM_NOTIFYTRAY; tnd.hIcon = hIcon; if(pszTip) lstrcpyn(tnd.szTip, pszTip, sizeof(tnd.szTip)); else tnd.szTip[0] = '\0'; bResult = Shell_NotifyIcon(dwMessage, &tnd); return bResult; }
- 创建雪花数组。
在这个应用程序中,每个雪花都被创建为一个非模式对话框窗口,并具有自己基于计时器的移动函数。
CRect rcWorkArea; SystemParametersInfo(SPI_GETWORKAREA,0,(LPVOID)&rcWorkArea,0); int nScreenWidth = rcWorkArea.Width(); int nTimer = 5; int nPosX = 0; srand((unsigned)time(NULL)); for(int i=0;i<10;i++) // 10 snow flakes { nTimer = abs(rand()*50/RAND_MAX); nPosX = abs(rand()*nScreenWidth/RAND_MAX); CFlakeDlg* fd = new CFlakeDlg(nTimer,nPosX,this); if(fd->Create(IDD_FLAKE,this)) m_arSnowFlakes.Add(fd); }
- 从位图中创建雪花形状。
在运行窗口之前,我们需要创建一个雪花区域,将窗口显示为真正的雪花。我使用了 Jean-Edouard Lachand-Robert 在 这里发布的文章中的 '
BitmapToRegion
' 函数。 - 最后一步:启动计时器并享受。
最后要做的事情是启动计时器并查看雪花如何移动。我使用了下面一个非常简单的算法,但足以显示桌面上的雪花移动。
void CFlakeDlg::OnTimer(UINT nIDEvent) { if(nIDEvent == 1) { KillTimer(1); m_nCurrentY += 5; m_nCounter++; if(m_nCounter == 15) { if(((rand()*10/RAND_MAX)-5)>0) m_nIncrement = 1; else m_nIncrement = -1; m_nCounter = 0; } m_nCurrentX += m_nIncrement; if(m_nCurrentY>m_nScreenHeight) { m_nCurrentY = 0; m_nCurrentX = abs(rand()*m_nScreenWidth/RAND_MAX); m_nTimer = abs(rand()*50/RAND_MAX); } MoveWindow(m_nCurrentX,m_nCurrentY,17,17); SetTimer(1,m_nTimer,0); } CDialog::OnTimer(nIDEvent); }
这个例子可以通过在桌面上绘制雪堆、显示圣诞老人、雪人和其他对象来扩展。您可以尝试雪花的定位(顶部、最顶部、底部)、雪花的数量、下落速度等。
无论如何,我希望其他人觉得这段代码在圣诞节期间有用。请随时报告错误、问题或请求。