FlatLoadingRing.cs 5.6 KB
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Drawing.Drawing2D;

namespace Asa.Theme
{
    /// <summary>
    /// 加载时的环形动画
    /// </summary>
    public partial class FlatLoadingRing : FlatBase
    {
        private int _index = -1;
        private PointF _center;      //大圆中心
        private int _circleRadius;   //大圆半径
        private int _ringDiam;       //小圆直径
        private int _count;          //小圆个数
        private RectangleF[] _ringRect;  //小圆大小
        private System.Threading.Thread tRing;


        /// <summary>
        /// 加载时的环形动画
        /// </summary>
        public FlatLoadingRing()
        {
            InitializeComponent();
            Speed = 200;
            _count = 12;
            _ringDiam = 10;
            _circleRadius = 30;

            CalcSize();
            Refresh();
        }


        /// <summary>
        /// 转动的速度
        /// </summary>
        [Browsable(true), Category(""), Description("转动的速度"), DefaultValue(200)]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
        public int Speed { set; get; }

        /// <summary>
        /// 小圈圈的个数,3-100个
        /// </summary>
        [Browsable(true), Category(""), Description("小圈圈的个数,3-100个"), DefaultValue(12)]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
        public int RingCount
        {
            set
            {
                _count = value;
                if (_count < 3)
                    _count = 3;
                else if (_count > 100)
                    _count = 100;
                CalcSize();
                Refresh();
            }
            get
            {
                return _count;
            }
        }

        /// <summary>
        /// 小圈圈的半径
        /// </summary>
        [Browsable(true), Category(""), Description("小圈圈的半径"), DefaultValue(10)]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
        public int RingDiameter
        {
            set
            {
                _ringDiam = value;
                if (_ringDiam < 2)
                    _ringDiam = 2;
                CalcSize();
                Refresh();
            }
            get
            {
                return _ringDiam;
            }
        }

        /// <summary>
        /// 半径
        /// </summary>
        [Browsable(true), Category(""), Description("大圆形的半径"), DefaultValue(30)]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
        public int CircleRadius
        {
            set
            {
                _circleRadius = value;
                CalcSize();
                Refresh();
            }
            get
            {
                return _circleRadius;
            }
        }

        /// <summary>
        /// 开始转动
        /// </summary>
        public void Start()
        {
            _index = 0;
            tRing = new System.Threading.Thread(new System.Threading.ThreadStart(Process));
            tRing.Start();
        }

        /// <summary>
        /// 停止转动
        /// </summary>
        public void Stop()
        {
            _index = -1;
            if (tRing != null)
            {
                tRing.Abort();
                tRing = null;
            }
            Refresh();
        }





        /// <summary>
        /// 计算大小
        /// </summary>
        protected override void CalcSize()
        {
            _center = new PointF(Width / 2f, Height / 2f);
            //_radius = Math.Min(_center.X, _center.Y) / 2f;
            _ringRect = new RectangleF[_count];
            float angle = 360f / _count;

            for (int i = 0; i < _ringRect.Length; i++)
            {
                double radian = (i * angle) * Math.PI / 180;
                float x = Convert.ToSingle(Math.Cos(radian) * _circleRadius);
                float y = Convert.ToSingle(Math.Sin(radian) * _circleRadius);
                PointF pt = new PointF(_center.X + x, _center.Y + y);
                _ringRect[i] = new RectangleF(pt.X - _ringDiam / 2f, pt.Y - _ringDiam / 2f, _ringDiam, _ringDiam);
            }

        }

        private void Process()
        {
            while (true)
            {
                Invoke(new Action(() => { Refresh(); }));
              
                _index++;
                if (_index == _ringRect.Length) _index = 0;
                System.Threading.Thread.Sleep(Speed);
            }
        }

        private void FlatLoadingRing_Paint(object sender, PaintEventArgs e)
        {
            //双缓冲
            BufferedGraphicsContext current = BufferedGraphicsManager.Current;
            BufferedGraphics bg = current.Allocate(CreateGraphics(), DisplayRectangle);
            Graphics g = bg.Graphics;

            //高质量
            g.SmoothingMode = SmoothingMode.HighQuality;
            g.CompositingQuality = CompositingQuality.HighQuality;
            g.InterpolationMode = InterpolationMode.HighQualityBicubic;

            g.Clear(Common.BACK_COLOR);
            for (int i = 0; i < _ringRect.Length; i++)
            {
                if (i == _index)
                    g.FillEllipse(Common.BLUE_BRUSH, _ringRect[i]);
                else
                    g.DrawEllipse(Common.BORDER_PEN, _ringRect[i]);
            }

            bg.Render();
            bg.Dispose();
        }
    }
}