随着圣诞节的到来,想到了制作一些有趣的桌面玩具。在网上搜索,可以很容易地找到许多适合任何场合的桌面礼物,包括圣诞节。不幸的是,没有找到任何源代码或开源样本的桌面动画。因此,决定创建自己的应用程序,让桌面上的其他窗口下雪。从互联网上,可以看到许多作者使用不同的方法在桌面上显示雪花。尽量使应用程序尽可能简单,并决定开发一个带有多个子雪花窗口的系统托盘应用程序。认为,这种方法最简单,但在内存和视频使用方面有一些限制。
创建主窗口。需要创建一个隐藏的框架窗口,并防止同时打开多个“雪”窗口。以下代码片段显示了如何做到这一点:
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);
// ...
}
安装系统托盘图标。
int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
// ...
SetTrayIcon(NIM_ADD, m_hIcon, "Desktop Snow");
// ...
}
创建雪花数组。在这个应用程序中,每片雪花都被创建为一个非模态对话框窗口,有自己的定时器依赖的运动函数。
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);
}