C#沙漏加载动画控件(纯代码完整可用!!!!!!)

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Threading;

namespace WindowsFormsApplication12
{
    class Loading : Control
    {
        const double k3 = 1.7320508075688772935274463415059;//根号3
        const int w = 12;//边框条形宽
        const int a1 = 40;
        const int a2 = 40;
        int a3 = 26;
        int h3 = 0;
        const double b = 0.8f;

        int ox = 0;
        int oy = 0;
        int ix = 0;
        int iy = 0;

        Color LineColor,inColor;
        bool isShowLine = false;
        //int cx = 0;
        //int cy = 0;

        /// <summary>
        /// 数据加载动画控件
        /// </summary>
        /// <param name="parent">父窗口</param>
        /// <param name="startPoint">开始位置</param>
        /// <param name="LineColor">外边框颜色</param>
        /// <param name="inColor">内沙子颜色</param>
        /// <param name="inColor">是否显示沙漏线</param>
        public Loading(Control parent, Point startPoint, Color LineColor, Color inColor, bool isShowLine)
        {
            this.Parent = parent;
            this.Location = startPoint;
            this.Size = new Size(115, 115);
            this.LineColor = LineColor;
            this.inColor = inColor;
            this.isShowLine = isShowLine;
            //防止闪屏
            SetStyle(ControlStyles.UserPaint, true);
            SetStyle(ControlStyles.AllPaintingInWmPaint, true); // 禁止擦除背景.
            SetStyle(ControlStyles.DoubleBuffer, true);
            //cx = mul(w, k3 / 2.0);
            //cy = w / 2;

            ox = mul(a1, 1.0 / 2.0 * b);
            oy = mul(a1, k3 / 2.0 * b);

            ix = mul(a2, 1.0 / 2.0 * b);
            iy = mul(a2, k3 / 2.0 * b);

            a3 = a2 - 3 * (a2 / 2 - ix);
            h3 = mul(a3, k3 / 2.0);

            //Thread t = new Thread(new ThreadStart(thread));
            //t.Start();
        }

        /// <summary>
        /// 数据加载动画控件(使用默认的版本)
        /// </summary>
        /// <param name="parent">父窗口</param>
        /// <param name="startPoint">开始位置</param>
        /// <param name="inColor">是否显示沙漏线</param>
        public Loading(Control parent, Point startPoint, bool isShowLine)
        {
            this.Parent = parent;
            this.Location = startPoint;
            this.Size = new Size(115, 115);
            this.LineColor = Color.BlueViolet;
            this.inColor = Color.FromArgb(46, 161, 239);
            this.isShowLine = isShowLine;
            //防止闪屏
            SetStyle(ControlStyles.UserPaint, true);
            SetStyle(ControlStyles.AllPaintingInWmPaint, true); // 禁止擦除背景.
            SetStyle(ControlStyles.DoubleBuffer, true);
            //cx = mul(w, k3 / 2.0);
            //cy = w / 2;

            ox = mul(a1, 1.0 / 2.0 * b);
            oy = mul(a1, k3 / 2.0 * b);

            ix = mul(a2, 1.0 / 2.0 * b);
            iy = mul(a2, k3 / 2.0 * b);

            a3 = a2 - 3 * (a2 / 2 - ix);
            h3 = mul(a3, k3 / 2.0);

            //Thread t = new Thread(new ThreadStart(thread));
            //t.Start();
        }


        object locker = new object();
        bool isLoading = false;
        public void start()
        {
            lock (locker)
            {
                if (isLoading) return;
                isLoading = true;
                an = 0;
                process = 0f;
                up = true;
                Thread t = new Thread(new ThreadStart(thread));
                t.Start();
            }
        }
        public void stop()
        {
            lock (locker)
            {
                isLoading = false;
            }
        }

        float an = 0;
        float process = 0f;
        bool up = true;


        private void thread()
        {
            while (true && isLoading)
            {
                process += 0.1f;
                this.Invoke(new Action(() => { ro(); }), null);
                Thread.Sleep(100);
                if (process >= 1.0f)
                {
                    float end = 180f;
                    if (an >= 180f)
                        end = 360f;

                    while (an <= end && isLoading)
                    {
                        an += 30f;
                        this.Invoke(new Action(() => { ro(); }), null);
                        Thread.Sleep(100);
                    }
                    if (end >= 360f)
                        an = 0f;

                    an = 180f;
                    process = 0f;
                    up = false;
                }
            }
        }

        Point RoatePoint = new Point();

        Bitmap bm = null;
        private void ro()
        {
            if (bm != null)
                bm.Dispose();
            bm = new Bitmap(Width, Height);
            Graphics g = Graphics.FromImage(bm);
            g.SmoothingMode = SmoothingMode.AntiAlias;  //使绘图质量最高,即消除锯齿
            int mx = 0;
            int my = 0;
            GraphicsPath path_out = getPathOut(20, 20, ref mx, ref my);
            Brush brush_out = new SolidBrush(Color.BlueViolet);
            GraphicsPath path_int = getPathInt(mx + 3, my);
            Brush brush_int = new SolidBrush(Color.White);

            Matrix m = new Matrix();
            m.RotateAt(an, new Point(mx + 3, my));
            path_out.Transform(m);
            path_int.Transform(m);
            g.FillPath(brush_out, path_out);
            g.FillPath(brush_int, path_int);

            GraphicsPath path_Triangle1 = getTriangle(new Point(mx + 3, my), up, 1f - process);
            Brush brush_Triangle = new SolidBrush(Color.FromArgb(46, 161, 239));
            path_Triangle1.Transform(m);
            g.FillPath(brush_Triangle, path_Triangle1);

            GraphicsPath path_Triangle2 = getTriangle(new Point(mx + 3, my), !up, 1f);
            path_Triangle2.Transform(m);
            g.FillPath(brush_Triangle, path_Triangle2);

            GraphicsPath path_Triangle3 = getTriangle(new Point(mx + 3, my), !up, 1f - process);
            SolidBrush white_brush = new SolidBrush(Color.White);
            path_Triangle3.Transform(m);
            g.FillPath(white_brush, path_Triangle3);

            if ((an == 0f || an == 180f) && isShowLine)
            {
                Pen p = new Pen(brush_Triangle);
                g.DrawLine(p, new Point(mx + 3, my), new Point(mx + 3, my + h3 - 2));
                p.Dispose();
            }
            path_out.Dispose();
            path_int.Dispose();
            path_Triangle1.Dispose();
            path_Triangle2.Dispose();
            path_Triangle3.Dispose();
            brush_out.Dispose();
            brush_int.Dispose();
            brush_Triangle.Dispose();
            white_brush.Dispose();
            this.BackgroundImage = bm;
        }
        private GraphicsPath getPathOut(int x,int y,ref int mx, ref int my)
        {
            Point pL = new Point(0, 0);
            Point pR = new Point(0, 0);
            float y2 = 0;
            GraphicsPath path = new GraphicsPath();
            path.AddArc(new Rectangle(x, y, w, w), 150f, 120f);//120f

            PointF p1 = path.GetLastPoint();
            PointF p2 = new PointF(p1.X + a1, p1.Y);
            path.AddLine(p1, p2);
            y2 = p1.Y;
            mx = (int)p1.X + a1 / 2;

            pR = new Point((int)p2.X, (int)p2.Y + 1);
            path.AddArc(new Rectangle(pR, new Size(w,w)), 270f, 120f);

            p1 = path.GetLastPoint();
            p2 = new PointF(p1.X - ox, p1.Y + oy);
            path.AddLine(p1, p2);
            y2 = y2 + 2 * (p2.Y - y2);
            my = (int)p2.Y;

            p1 = new PointF(p2.X + ox, p2.Y + oy);
            path.AddLine(p2, p1);

            path.AddArc(new Rectangle(pR.X, (int)y2 - w, w, w), 330f, 90f);

            p1 = path.GetLastPoint();
            p2 = new PointF(p1.X - a1, p1.Y);
            path.AddLine(p1, p2);

            path.AddArc(new Rectangle(x, (int)y2 - w - 1, w, w), 90f, 120f);

            p1 = path.GetLastPoint();
            p2 = new PointF(p1.X + ox, p1.Y - oy);
            path.AddLine(p1, p2);

            
            return path;
        }
        private GraphicsPath getPathInt(int mx, int my)
        {
            GraphicsPath path = new GraphicsPath();
            int y = my - iy;
            int x = mx - a2 / 2;
            Point p1 = new Point(x, y);
            x += a2;
            Point p2 = new Point(x, y);
            path.AddLine(p1, p2);

            x -= ix;
            y += iy;
            p1 = p2;
            p2 = new Point(x, y);
            path.AddLine(p1, p2);
            RoatePoint = p2;

            x += ix;
            y += iy;
            p1 = p2;
            p2 = new Point(x, y);
            path.AddLine(p1, p2);

            x -= a2;
            p1 = p2;
            p2 = new Point(x, y);
            path.AddLine(p1, p2);

            x += ix;
            y -= iy;
            p1 = p2;
            p2 = new Point(x, y);
            path.AddLine(p1, p2);

            RoatePoint.Y = RoatePoint.Y - (RoatePoint.Y - p2.Y) / 2;
            return path;
        }
        private GraphicsPath getTriangle(Point m,bool isUp, float process)
        {
            int h = (int)((float)h3 * process);
            int a = (int)((float)a3 * process);
            GraphicsPath path = new GraphicsPath();
            Point p1 = new Point(m.X + a / 2, m.Y - h);
            Point p2 = new Point(m.X - a / 2, m.Y - h);
            if (isUp == false)
            {
                p1 = PointRotate(m, p1, 180f);
                p2 = PointRotate(m, p2, 180f);
            }
            path.AddLine(m, p1);
            path.AddLine(p1, p2);
            return path;
        }

        /// <summary> 
        /// 对一个坐标点按照一个中心进行旋转 
        /// </summary> 
        /// <param name="center">中心点</param> 
        /// <param name="p1">要旋转的点</param> 
        /// <param name="angle">旋转角度,笛卡尔直角坐标</param> 
        /// <returns></returns> 
        private Point PointRotate(Point center, Point p1, double angle)
        {
            Point tmp = new Point();
            double angleHude = angle * Math.PI / 180;/*角度变成弧度*/
            double x1 = (p1.X - center.X) * Math.Cos(angleHude) + (p1.Y - center.Y) * Math.Sin(angleHude) + center.X;
            double y1 = -(p1.X - center.X) * Math.Sin(angleHude) + (p1.Y - center.Y) * Math.Cos(angleHude) + center.Y;
            tmp.X = (int)x1;
            tmp.Y = (int)y1;
            return tmp;
        } 
        private int mul(int a, double b)
        {
            double c = (double)a * b;
            return (int)c;
        }
    }
}
上面是控件的封装,要看完整例子,请下载工程文件(感觉好用要给顶一下哦!)


评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值