在安装微软键鼠驱动时看到一个新样式的 loading 动画不错,但是搜索不到相应的图片,遂用代码模拟,先看下效果图
以下是 C# WinForm 的实现代码,放入一窗体代码页中
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Runtime.InteropServices;
using System.Threading;
using System.Windows.Forms;
namespace WinForm
{
public partial class Form1 : Form
{
private const int WM_ANIM = 0x410;
private Point startPoint;
private Token token;
public Form1()
{
InitializeComponent();
var rect = this.ClientRectangle;
var left = (rect.Width - Square.Width) / 2 + rect.X;
var top = (rect.Height - Square.Size.Height) / 2 + rect.Y;
this.startPoint = new Point(left, top);
}
[DllImport("User32.dll", EntryPoint = "PostMessageW")]
[return: MarshalAs(UnmanagedType.Bool)]
private extern static bool PostMessage(IntPtr hWnd, uint Msg,
IntPtr wParam, IntPtr lParam);
protected override void OnVisibleChanged(EventArgs e)
{
base.OnVisibleChanged(e);
if (this.token != null)
{
this.token.IsCancel = true;
this.token = null;
}
if (this.Visible)
{
var token = new Token { Handle = this.Handle };
this.token = token;
ThreadPool.QueueUserWorkItem(v =>
{
var tk = (Token)v;
CONTINUE:
Thread.Sleep(35);
if (!tk.IsCancel)
{
token.Index = token.Index < Square.LeftArr.Length ?
token.Index + 1 : Square.StartIndex;
if (Form1.PostMessage(tk.Handle, Form1.WM_ANIM,
IntPtr.Zero, IntPtr.Zero))
{
goto CONTINUE;
}
}
}, token);
}
}
protected override void OnPaint(PaintEventArgs e)
{
base.OnPaint(e);
if (this.token != null)
{
var start = this.token.Index;
if (start < 0)
{
start = -start % Square.Space;
if (start > 0)
{
start = Square.Space - start;
}
}
var end = this.token.Index + ((Square.Num - 1) * Square.Space + 1);
if (end > Square.LeftArr.Length)
{
end = Square.LeftArr.Length;
}
for (; start < end; start += Square.Space)
{
var point = new Point(Square.LeftArr[start] + this.startPoint.X,
this.startPoint.Y);
e.Graphics.FillRectangle(Brushes.CornflowerBlue,
new Rectangle(point, Square.Size));
}
}
}
protected override void WndProc(ref Message m)
{
switch (m.Msg)
{
case Form1.WM_ANIM:
this.Invalidate(new Rectangle(this.startPoint,
new Size(Square.Width, Square.Size.Height)));
break;
default:
base.WndProc(ref m);
break;
}
}
private class Square
{
public static readonly int[] LeftArr;
public static readonly Size Size = new Size(5, 5);
public static readonly int Num = 5;
public static readonly int Space = 5;
public static readonly int Width;
public static readonly int StartIndex;
static Square()
{
var list = new List<int>();
var start = 24;
var dv = 6;
do
{
for (var i = 0; i < 2; ++i)
{
list.Add(start);
}
start -= dv;
} while (--dv > 0);
for (var i = 0; i < 15; ++i)
{
list.Add(start);
}
Square.LeftArr = new int[list.Count * 2 + 1];
var li = 1;
for (var i = 0; i < list.Count; ++i, ++li)
{
Square.LeftArr[li] = Square.LeftArr[i] + list[i];
}
for (var i = list.Count - 1; i >= 0; --i, ++li)
{
Square.LeftArr[li] = Square.LeftArr[li - 1] + list[i];
}
Square.Width = Square.LeftArr[Square.LeftArr.Length - 1] + Square.Size.Width;
Square.StartIndex = -(Square.Num - 1) * Square.Space;
}
}
private class Token
{
public bool IsCancel = false;
public IntPtr Handle;
public int Index = Square.StartIndex;
}
}
}