C#自定义加载框、等待框、加载层

自制简单实用加载层

1.主要方式就是通过graphics围绕中心点绘制N个小圆实现动态的效果,一圈之后变换颜色继续绘制。

主要用到graphics的TranslateTransform、RotateTransform方法,代码如下:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace FormLoading.Dialog
{
    public enum EMLoadingType { Small, Middle, Large}
    public partial class FormLoading : BaseDialog
    {
        public Point ptOrigin = new Point(0, 0);
        private int offset = 30;
        private int angle = 0;
        private int ConstAngle = 36;
        private int CircleWidth = 20;

        private Pen pLight = new Pen(Color.LightBlue, 2f);
        private Brush bLight = new SolidBrush(Color.LightBlue);
        private Brush bDark = new SolidBrush(Color.SkyBlue);
        private EMLoadingType loadType = EMLoadingType.Middle;
        public bool Finished { get; set; } = false;
        public bool Success { get; set; } = false;
        public string ResultStr { get; set; }
        public FormLoading()
        {
            InitializeComponent();
        }
        public void SetLoading(EMLoadingType type,string title,string tips)
        {
            ShowTips(tips);
            TitleText = title;
            loadType = type;
        }
        public void EndLoading(bool success)
        {
            tmLoading.Enabled = false;
            this.Finished = true;
            this.Success = success;
            if(this.Visible == true)
                this.Close();
        }
        public void ShowTips(string tips)
        {
            labTips.Text = tips;
        }
        private void DrawCircle(Graphics g, Brush b, Pen p)
        {
            g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
            RectangleF rectStart = new RectangleF();
            rectStart.X = ptOrigin.X + offset;
            rectStart.Y = ptOrigin.Y - CircleWidth / 2;
            rectStart.Width = CircleWidth;
            rectStart.Height = CircleWidth;
            //g.DrawEllipse(p, rectStart);
            g.FillEllipse(b, rectStart);
        }

        private void tmLoading_Tick(object sender, EventArgs e)
        {
            Graphics g = this.pnlForm.CreateGraphics();
            Brush b;
            if (angle > 720 - ConstAngle)
                angle = 0;
            if (angle <= 360 - ConstAngle)
                b = bLight;
            else
                b = bDark;
            g.TranslateTransform(Width / 2, Height / 2);
            g.RotateTransform(angle);
            DrawCircle(g, b, pLight);
            angle += ConstAngle;
            g.Dispose();
            
        }
        private void btnSmall_Click(object sender, EventArgs e)
        {
            Start_SmallLoading();
        }
        
        private void btnMiddle_Click(object sender, EventArgs e)
        {
            Start_MiddleLoading();
        }

        private void btnLarge_Click(object sender, EventArgs e)
        {
            Start_LargeLoading();
        }
        private void Start_SmallLoading()
        {
            tmLoading.Enabled = false;
            Graphics g = this.pnlForm.CreateGraphics();
            g.Clear(SystemColors.Control);
            g.Dispose();

            angle = 0;
            offset = 20;
            ConstAngle = 36;
            CircleWidth = 13;
            tmLoading.Enabled = true;
        }
        private void Start_MiddleLoading()
        {
            tmLoading.Enabled = false;
            Graphics g = this.pnlForm.CreateGraphics();
            g.Clear(SystemColors.Control);
            g.Dispose();

            angle = 0;
            offset = 30;
            ConstAngle = 36;
            CircleWidth = 20;
            tmLoading.Enabled = true;
        }
        private void Start_LargeLoading()
        {
            tmLoading.Enabled = false;
            Graphics g = this.pnlForm.CreateGraphics();
            g.Clear(SystemColors.Control);
            g.Dispose();

            angle = 0;
            offset = 40;
            ConstAngle = 36;
            CircleWidth = 25;
            tmLoading.Enabled = true;
        }

        private void FormLoading_Shown(object sender, EventArgs e)
        {
            labTips.BackColor = SystemColors.Control;
            switch (loadType)
            {
                case EMLoadingType.Small:
                    Start_SmallLoading();
                    break;
                case EMLoadingType.Middle:
                    Start_MiddleLoading();
                    break;
                case EMLoadingType.Large:
                    Start_LargeLoading();
                    break;
            }
        }
    }
}

效果图如下:

 

 

2. 上面只是实现了加载层的效果,具体使用需要调用相应方法用模态方式展示,并在后台用线程完成自己的耗时操作,然后关闭加载层,中间可以用invoke方法回显具体进度信息。方法如下:

//owner:主线程UIcontrol,Application.OpenForms["xxx"]就可以,param是线程处理自己的耗时业务参数
public
static void DownLoadDataCallBack(Control owner, FormLoading loadingFrom, object param) { Action EndLoadingEvent; Action<string> ShowTipsEvent; bool success = false; string resultStr = ""; void ExecuteTrd() { //这里dataRlt采用Tuple返回<bool,string>两个返回结果方法好用! var dataRlt = DownloadXXXX(param); success = dataRlt.Item1; resultStr = dataRlt.Item2; owner.Invoke(EndLoadingEvent); } void EndLoading() { loadingFrom.ResultStr = resultStr; loadingFrom.EndLoading(success); } void SetTips(string tips) { loadingFrom.ShowTips(tips); } EndLoadingEvent = EndLoading; ShowTipsEvent = SetTips; if (loadingFrom != null && param != null) { Thread trd = new Thread(ExecuteTrd); trd.Start(); } }

3.下面是封装的弹出加载框方法,调用就可以显示。

 

/// <summary>
        /// 统一弹出加载框方法
        /// </summary>
        /// <param name="owner">UI窗体</param>
        /// <param name="title">窗体名称</param>
        /// <param name="tips">加载显示信息</param>
        /// <param name="callBack">业务回调方法(耗时)</param>
        /// <param name="param">业务回调参数</param>
        /// <param name="type">加载圆大小</param>
        /// <returns></returns>
        public Tuple<bool,string> ShowLoadingTips(Control owner, string title, string tips, Action<Control, FormLoading, object> callBack,
            object param, EMLoadingType type = EMLoadingType.Middle)
        {
            Logger.Debug("ShowLoadingTips");
            FormLoading loadingDialog = new FormLoading();
            loadingDialog.SetLoading(type, title, tips);
            if(callBack != null)
                callBack(owner, loadingDialog, param);
            if(loadingDialog != null && !loadingDialog.Finished)
                loadingDialog.ShowDialog();
            return new Tuple<bool, string>(loadingDialog.Success,loadingDialog.ResultStr);
        }

 

 

 

不错的业务耗时解决方案^_^。

 

posted @ 2020-09-01 21:42  胖达没有海  阅读(1264)  评论(0编辑  收藏  举报