C# WinForm 进度条可复用窗口设计

时间:2022-09-11 13:15:08

    相信很多工作之后经常需要做进度条,尤其是客户端程序上传文件或者执行某些任务的时候,有进度条会让界面友好很多。最近也是蛋疼到不行,新接手的项目里一会要执行单个任务的,一会要执行多个任务的,所以进度条的个数也不确定,还要组长还跑来跟我要进度条窗口,索性自己动手画一个可复用的进度条窗口,废话少说,先上图


单进度条模式

C# WinForm 进度条可复用窗口设计


双进度条模式

C# WinForm 进度条可复用窗口设计


窗口是纯手绘的,只需要设置一个参数就能显示对应个数的进度条,这样能满足多数情况的使用。


下面是简单的代码实现


namespace HApplication
{
    public delegate void Func();
    public delegate void SetKeyValDelegate<T1, T2>(T1 key, T2 val);
    public delegate void ExcuteDelegate(TransferDlg dlg, params object[] args);

    public class TransferDlg : Form
    {        
        #region << 变量 >>
        private static TransferDlg _cur = null;
        private Thread _thread = null;
        #endregion
        private void OnCancelClick(object sender, EventArgs e)
        {
            if (_thread.ThreadState != ThreadState.Stopped)
            {
                _thread.Abort();
            }

            this.Close();
        }

        private void OnMouseMove(object sender, MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Left)
            {
                ReleaseCapture();
                SendMessage(this.Handle, WM_NCLBUTTONDOWN, (IntPtr)HTCAPTION, IntPtr.Zero);
            }
        }

        public new void Close()
        {
            if (this.InvokeRequired)
            {
                this.Invoke(new Func(Close));
                return;
            }

            base.Close();
        }

        #region << 接口 >>
        /// <summary>
        /// 启用阻塞式对话框显示进度条
        /// </summary>
        /// <param name="num">指示该对话框中进度条的个数</param>
        /// <param name="func">期间需要执行的函数</param>
        /// <param name="args">为执行函数提供参数</param>
        public static void Start(int num, ExcuteDelegate func, params object[] args)
        {
            _cur = new TransferDlg(num);

            _cur._thread = new Thread(new ThreadStart(delegate()
            {
                func(_cur, args);
                _cur.Close();
            }));
            _cur._thread.Name = "Work Thread";
            _cur._thread.Start();

            _cur.ShowDialog();
        }
    }
}


调用的时候也非常容易


class App
    {
        [STAThread]
        static void Main(string[] args)
        {
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            TransferDlg.Start(1, Run1, 100000, 100);
            TransferDlg.Start(2, Run2, 1000, 100);
        }

        public static void Run1(TransferDlg dlg, params object[] args)
        {
            int arg0 = (int)args[0];

            dlg.SetMaxValue(0, arg0);
            for (int i = 0; i < arg0; i++)
            {
                dlg.SetCurValue(0, i);
                dlg.SetText(0, string.Format("正在上传文件 {0} / {1}", i, arg0));
            }
        }

        public static void Run2(TransferDlg dlg, params object[] args)
        {
            int arg0 = (int)args[0];
            int arg1 = (int)args[1];

            dlg.SetMaxValue(0, arg0);
            for (int i = 0; i < arg0; i++)
            {
                dlg.SetCurValue(0, i);
                dlg.SetText(0, string.Format("正在上传文件 {0} / {1}", i, arg0));
                dlg.SetMaxValue(1, arg1);
                for (int j = 0; j < arg1; j++)
                {
                    dlg.SetCurValue(1, j);
                    dlg.SetText(1, string.Format("文件上传进度 {0} / {1}", j, arg1));
                }
            }
        }
    }


写好需要执行任务的函数,参数为上文中的

void ExcuteDelegate(TransferDlg dlg, params object[] args)
调用TransferDlg的静态方法 Start,第一个参数为要显示进度条的个数,第二参数为你写的要执行任务的函数,第三个参数是变参,可不传,这些变参将传给你要执行的函数。

在函数内部可以直接dlg中的值,已写线程安全,TransferDlg提供四个公开函数,分别用于设置 标题,文本,进度条最大,进度条当前值。

调用方法如:

dlg.SetTitle("标题");
dlg.SetText(0, string.Format("正在上传文件 {0} / {1}", i, arg0));
dlg.SetMaxValue(0, 100);
dlg.SetCurValue(0, 10);

源码已上传至CSDN,感觉有用或者有兴趣的可以去看看,俾人一向不喜欢收积分。窗口样子要是不喜欢可以自己改。
下载地址 源代码
下如果觉得实用或者感兴趣,记得来点个赞。要知道我这可是无偿熬夜