微软安装程序 loading 动画模拟

在安装微软键鼠驱动时看到一个新样式的 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;
        }
    }
}


 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值