|

Introduction
Every time the Christmas holidays come, I think about making funny toys for my desktop.
Searching through the Internet, you can easily find many wonderful desktop gifts for any occasion, including Christmas time. Unfortunately, I couldn't find any source code or open source samples of such desktop animations.
So, I decided to create my own application that makes it snow on the desktop over other windows. As I can see from the Internet, many authors use different ways to display snow fall on the desktop. I tried to create my application as simple as possible, and decided to develop a system tray application with numerous child flake windows. I think, this method is the simplest, but has a few limitations regarding memory and video usage.
General Steps
- Creating the main window.
We need to create a hidden frame window and prevent more than one open ‘Snow’ window at the same time. The following code fragment shows how to do this: 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;
}
...
- Installing the system tray icon.
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;
}
- Creating the array of snow flakes.
In this application, each snow flake has been created as a non-modal dialog window with its own timer-dependent movement function. 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++)
{
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);
}
- Creating a flake shape from the bitmap.
Before running the window, we need to create a flake region that shows the window as a real snow flake. I used the 'BitmapToRegion' function from the article of Jean-Edouard Lachand-Robert, posted here.
- The last step: start the timer and enjoy.
The last thing to do is start the timer and see how the flakes move. I used a very simple algorithm below, but it is sufficient to show snow movement on the desktop.
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);
}
This example can be extended by drawing snowdrifts on the desktop, displaying Santa, snowman, and other objects. You can experiment with the flakes positioning (top, topmost, bottom), number of flakes, falling speed etc.
Anyway, I hope others find this code useful for the Christmas holidays. Please feel free to report errors, issues, or requests.
| You must Sign In to use this message board. |
|
| | Msgs 1 to 25 of 49 (Total in Forum: 49) (Refresh) | FirstPrevNext |
|
 |
|
|
 |
|
|
 |
|
|
Thanks for your input. The idea of this application is to move flake-shaped windows on the desktop. So, when the flake is moving over the Java window (or another window), this background window (ie Java window in this case) should be repainted every flake step. Any background window do this, but Java-powered window requires more GDI memory (due to JRE architecture), and flickering is more visible. You can try to change the flakes positioning (topmost, top) and moving steps to reduce flickering. Happy New Year, have a nice Holidays!
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
It would be neat if snow accumulated (piled-up) on the icons. But, I think, this might be quite a challenging feature.
Cheers, Nick
|
| Sign In·View Thread·PermaLink | 2.00/5 (1 vote) |
|
|
|
 |
|
|
If you need to have a nice snowdrift over the icon, you should use drawing functions over the desktop window as described in previous messages.
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
 |
|
|
Thanks, I tried to develop this application as simple as possible. Please feel free to add any features you want.
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
 |
|
|
Hi All,
Very nice application. Unfortunately, I noticed a problem when Active desktop is running. It has a weird flicker problem. I'm running Windows 2000.
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
 |
|
|
 |
|
|
 |
|
|
 |
|
|
 |
|
|
 |
|
|
Thank you very much for your input. This idea was taken from the Microsoft's articles Q141752 and Q109175. I know about existent problems, and using of FindWindow can be dangerous if the classname (or window caption) is undefined. I hope not in this application . Anyway, you can use Mutex instead:
BOOL bAlreadyRunning = FALSE;
HANDLE hMutexOneInstance = ::CreateMutex( NULL, FALSE, _T("SnowParentWindow")); bAlreadyRunning = ( ::GetLastError() == ERROR_ALREADY_EXISTS || ::GetLastError() == ERROR_ACCESS_DENIED); if(bAlreadyRunning) return FALSE;
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
Hi Igor,
Igor Tolmachev wrote: Microsoft's articles Q141752 and Q109175
They got me too...
Igor Tolmachev wrote: BOOL bAlreadyRunning = FALSE; HANDLE hMutexOneInstance = ::CreateMutex( NULL, FALSE, _T("SnowParentWindow")); bAlreadyRunning = ::GetLastError() == ERROR_ALREADY_EXISTS; bAlreadyRunning |= ::GetLastError() == ERROR_ACCESS_DENIED;
if(bAlreadyRunning) return FALSE;
That is the method I use (though it does have a small chance of performing incorrectly). But it does not depend on other programs to be in a responsive state.
Jeff
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
 |
|
|
 |
|
|
 |
|
|
I'm very impressed with your program! But there is a small glitch To reproduce it create a selection using the mouse (press left button and move the mouse around) on the desktop in the area where snowflakes flying and after snowflake crosses the dashed selection border it looks like snowflake "eat" a selection border. Also it would be great if there is a few settings are available: snowflakes count, drop speed and "always on top"! Thank you very much.
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
Thank you very much. You can see previous messages regarding "always on top" feature. Please feel free to add anything you want, including snowflakes count or snowdrifts. Merry X-Mas!
|
| Sign In·View Thread·PermaLink | 2.00/5 (1 vote) |
|
|
|
 |
|
|
Good job!
but when I click show desktop button at quick launch bar,it's hind.
How can I solve this problem?
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
Yes, I agree with some of the others. I'd love to see it accumulate and also, if there was a way to keep it on top of the other windows...

|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
You can put the flakes on top by usign ::SetWindowPos(m_hWnd,HWND_TOPMOST,0,0,17,17,SWP_NOMOVE); in the CFlakeDlg::OnInitDialog() If you want to have snowdrifts or some text on the desktop, you can start to work with drawing functions: HWND hDesktop = ::GetDesktopWindow(); HDC hdc = ::GetWindowDC(hDesktop); ::TextOut(hdc, 100, 100, "Merry X-Mas!!!", 14); ::ReleaseDC(hDesktop, hdc);
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
General News Question Answer Joke Rant Admin
|