(桌面)飘落的雪花






4.58/5 (18投票s)
使用 GDI+ 和透明窗体

引言
首先,我必须说明这不是我的主意,它更像是将一个 C++ 示例以不同的方式移植到 C#。如果您想查看原文,请点击这里。(感谢Igor Tolmachev 提供的精彩想法。)我改变了它的工作方式(从多个对话框改为单个窗体),并添加了一些新功能(例如旋转、缩放等)。
使用程序
只需运行可执行文件即可。要关闭程序,请双击代表雪花的小托盘图标。
Using the Code
程序本身使用一个无边框窗体(大小调整为匹配屏幕分辨率)和透明的背景色来绘制雪花。我没有使用多个窗体/对话框(我不喜欢这种方法),而是在一个窗体上使用 GDI+ 进行绘图。
public MainForm() {
InitializeComponent();
//We paint our control ourself
//and need a double buffer to prevent flimmering
SetStyle(
ControlStyles.UserPaint | ControlStyles.AllPaintingInWmPaint |
ControlStyles.DoubleBuffer, true);
//Resize and relocate form to match Screen settings
Location = new Point(Screen.PrimaryScreen.Bounds.X,
Screen.PrimaryScreen.Bounds.Y);
Width = Screen.PrimaryScreen.Bounds.Width;
Height = Screen.PrimaryScreen.Bounds.Height;
}
雪花本身保存在一个List<SnowFlake>
中。Snowflake
是一个容器类,包含雪花的当前数据/位置(X
、Y
、Rot
、Scale
)和速度/变化量(XVel
、YV
、el
RotVel
)。
主要函数是OnTick
方法,它分为几个步骤:
- 增加滴答计数(例如,每滴答添加雪花会有点多)。
- 生成新的雪花(如果满足适当的条件)。
- 移动所有雪花(通过将速度添加到数据值)。
- 删除位于屏幕/任务栏下方的雪花。
- 渲染雪花。
雪花是通过定义一个userpaint
方法MainForm_Paint
并调用Refresh()
来使窗体失效来绘制的。需要Refresh()
,因为它支持双缓冲,而MainForm_Paint(CreateGraphics())
则不支持。在本例中,我使用了 GDI+ 的矩阵功能来旋转和缩放雪花。
foreach (SnowFlake s in SnowFlakes) {
g.ResetTransform();
g.TranslateTransform(-16, -16, MatrixOrder.Append); //Align our flakes to the center
g.ScaleTransform(s.Scale, s.Scale, MatrixOrder.Append); //Scale them..
g.RotateTransform(s.Rotation, MatrixOrder.Append); //Rotate them..
//Move them to their appropriate location
g.TranslateTransform(s.X, s.Y, MatrixOrder.Append);
g.DrawImage(Snow, 0, 0); //draw them
}
雪花图像使用 GDI+ 函数绘制,然后缓存为 32x32 像素大小以提高性能。(当您绘制大量线条时,GDI+ 速度很慢。)
自定义!
只需增加雪花生成数量/速度,您就可以获得一些非常不错的效果。但请注意,GDI+ 的速度不如看起来那么快,它会增加 CPU 使用率(尤其是在使用矩阵时)。
历史
- 2007 年 10 月 3 日:初始发布