This article was posted on last Christmas. Now I move this to my new home.
It’s very hard to see snow here, but we can create a desktop toy to simulate snowing on your screen. If you run this desktop toy, you will see snow falling from top of your screen. The compiled version can be downloaded here
- Simply create a WinForm application in Visual Studio 2008,and change the Form properties as following picture shows. If you don’t have Visual Studio 2008, you also can download Visual Studio Express for free
- Dump the following code and run it.
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;
using System.Runtime.InteropServices;
using System.Windows.Forms;
namespace Snow
{
public partial class Form1 : Form
{
private Bitmap m_Snow;
private static readonly Random rand = new Random();
private readonly List SnowFlakes = new List();
private int Tick = 0;
private class SnowFlake
{
public float Rotation;
public float RotVelocity;
public float Scale;
public float X;
public float XVelocity;
public float Y;
public float YVelocity;
}
Image screenImage;
private void Form1_Load(object sender, EventArgs e)
{
////
screenImage = new Bitmap(Screen.PrimaryScreen.Bounds.Width, Screen.PrimaryScreen.Bounds.Height);
}
private void SetBackground(Image img)
{
try
{
Bitmap bitmap = (Bitmap)img;
if (bitmap.PixelFormat != PixelFormat.Format32bppArgb)
{
throw new ApplicationException();
}
IntPtr hObject = IntPtr.Zero;
IntPtr zero = IntPtr.Zero;
IntPtr hDC = Win32.GetDC(IntPtr.Zero);
IntPtr ptr2 = Win32.CreateCompatibleDC(hDC);
try
{
hObject = bitmap.GetHbitmap(Color.FromArgb(0));
zero = Win32.SelectObject(ptr2, hObject);
Win32.Size size2 = new Win32.Size(bitmap.Width, bitmap.Height);
Win32.Size psize = size2;
Win32.Point point3 = new Win32.Point(0, 0);
Win32.Point pprSrc = point3;
point3 = new Win32.Point(base.Left, base.Top);
Win32.Point pptDst = point3;
Win32.BLENDFUNCTION pblend = new Win32.BLENDFUNCTION();
pblend.BlendOp = 0;
pblend.BlendFlags = 0;
pblend.SourceConstantAlpha = 0xff;
pblend.AlphaFormat = 1;
Win32.UpdateLayeredWindow(this.Handle, hDC, ref pptDst, ref psize, ptr2, ref pprSrc, 0, ref pblend, 2);
}
catch (Exception exception1)
{
Exception exception = exception1;
throw exception;
}
finally
{
Win32.ReleaseDC(IntPtr.Zero, hDC);
if (hObject != IntPtr.Zero)
{
Win32.SelectObject(ptr2, zero);
Win32.DeleteObject(hObject);
}
Win32.DeleteDC(ptr2);
}
}
catch (Exception e)
{
MessageBox.Show(e.Message);
}
}
protected override System.Windows.Forms.CreateParams CreateParams
{
get
{
System.Windows.Forms.CreateParams createParams = base.CreateParams;
createParams.ExStyle |= 0x80000;
return createParams;
}
}
private Bitmap Snow
{
get
{
if (m_Snow == null)
{
m_Snow = new Bitmap(32, 32);
using (Graphics g = Graphics.FromImage(m_Snow))
{
g.SmoothingMode = SmoothingMode.AntiAlias;
g.Clear(Color.Transparent);
g.TranslateTransform(16, 16, MatrixOrder.Append);
Color black = Color.FromArgb(1, 1, 1);
Color white = Color.FromArgb(255, 255, 255);
DrawSnow(g, new SolidBrush(black), new Pen(black, 3f));
DrawSnow(g, new SolidBrush(white), new Pen(white, 2f));
g.Save();
}
}
return m_Snow;
}
}
public Form1()
{
InitializeComponent();
SetStyle(ControlStyles.UserPaint | ControlStyles.AllPaintingInWmPaint | ControlStyles.DoubleBuffer, true);
}
private void OnTick(object sender, EventArgs args)
{
Tick++;
//new snow flake
if (Tick % 5 == 0 && rand.NextDouble() < 0.30)
{
SnowFlake s = new SnowFlake();
s.X = rand.Next(-20, this.Width + 20);
s.Y = 0f;
s.XVelocity = (float)(rand.NextDouble() - 0.5f) * 2f;
s.YVelocity = (float)(rand.NextDouble() * 3) + 1f;
s.Rotation = rand.Next(0, 359);
s.RotVelocity = rand.Next(-3, 3) * 2;
if (s.RotVelocity == 0)
{
s.RotVelocity = 3;
}
s.Scale = (float)(rand.NextDouble() / 2) + 0.75f;
SnowFlakes.Add(s);
}
//To draw snowflake
Graphics g = Graphics.FromImage(screenImage);
g.Clear(Color.Transparent);
g.SmoothingMode = SmoothingMode.HighSpeed;
for (int i = 0; i < SnowFlakes.Count; i++) { SnowFlake s = SnowFlakes[i]; s.X += s.XVelocity; s.Y += s.YVelocity; s.Rotation += s.RotVelocity; s.XVelocity += ((float)rand.NextDouble() - 0.5f) * 0.7f; s.XVelocity = Math.Max(s.XVelocity, -2f); s.XVelocity = Math.Min(s.XVelocity, +2f); if (s.Y > this.Height)
{
SnowFlakes.RemoveAt(i);
}
else
{
g.ResetTransform();
g.TranslateTransform(-16, -16, MatrixOrder.Append); //pan
g.ScaleTransform(s.Scale, s.Scale, MatrixOrder.Append); //scale
g.RotateTransform(s.Rotation, MatrixOrder.Append); //rotate
g.TranslateTransform(s.X, s.Y, MatrixOrder.Append); //pan
g.DrawImage(Snow, 0, 0); //draw
////g.Dispose();
}
}
g.Dispose();
SetBackground(screenImage);
}
private static void DrawSnow(Graphics g, Brush b, Pen p)
{
const int a = 6;
const int a2 = a + 2;
const int r = 2;
g.DrawLine(p, -a, -a, +a, +a);
g.DrawLine(p, -a, +a, +a, -a);
g.DrawLine(p, -a2, 0, +a2, 0);
g.DrawLine(p, 0, -a2, 0, +a2);
g.FillEllipse(b, -r, -r, r * 2, r * 2);
}
}
}