[C#] (原创)进度等待窗口(附:自定义控件的使用)
一、前言
技术没有先进与落后,只有合适与不合适。
在程序当中,经常有耗时较长的操作,为了给用户更好的体验,就需要给用户一个及时的反馈,这种时候就需要用到进度等待窗口。
实现进度等待窗口的技术有很多,比如:BackgroundWorker、Thread等。
不过技术不是难点,难点在于怎么使等待窗口美观实用。所以本文中就基于前几篇的自定义控件:LProgressBar和LLabel,去实现进度等窗口。
相关文章:
[C#] (原创)一步一步教你自定义控件——04,ProgressBar(进度条)
[C#] (原创)一步一步教你自定义控件——05,Label(原生控件)
相信看完的你,一定会有所收获。
本文地址:https://www.cnblogs.com/lesliexin/p/14121618.html
二、前期分析
(一)为什么需要进度等窗口?
为了在执行耗时操作时,给用户更好的、更直观的体验。
(二)预期功能效果
1,功能
(1),支持“取消”操作,当然也支持“不能取消”操作。
(2),支持进度明确与进度不明确时显示不同样式。
(3),支持明细进度。
2,效果
Win7:


Win10:


三、开始实现
(一)布局窗体
1,新建窗体
(1),在工程上右击,选择“添加”->“窗体(Windows 窗体)”,命名为:LProgress.cs。

(2),修改窗体相关属性
Font:微软雅黑,9pt。比之默认的“宋体,9pt”的效果更加美观。
BackColor:White。更加美观,特别是在Win10上。
ForeColor:Black。为了防止被某些系统主题影响而显示的不是黑色。
FormBorderStyle:FixedDialog。使用户不可调用窗口尺寸。
MaximizeBox:False。不显示最大化按钮。
MinimizeBox:False。不显示最小化按钮。
ShowIcon:False。不显示窗口图标。
ShowInTaskbar:False。不在任务栏上显示图标。
TopMost:True。置顶显示窗口。
2,添加控件
这里需要说明一下,在添加控件时,如果如本文这样窗体与自定义控件工程在同一个解决方案中,那么在工具栏的最上方会自动显示当前工具中的自定义控件,选中即可使用。

如果是窗体与自定义控件工程不在同一个解决方案中,比如引用的是自定义控件的DLL文件,那么就需要将自定义控件DLL拖到工具栏上,此时工具栏上就会显示出里面的自定义控件。

(1)总体控件布局

(2)lPBar_Main(主进度)
控件:LProgressBar
关键属性:

(3)lPBar_Child(子进度)
控件:LProgressBar
关键属性:

(4)lbl_Main(主进度文本)
控件:LLabel
关键属性:

(5)lbl_Child(子进度文本)
控件:LLabel
关键属性:

(6)btn_Cancel(取消按钮)
控件:Button
关键属性:

(7)相关说明
这里说下lbl_Main和lbl_Child为什么不使用原生Label控件,而使用自定义LLabel控件。
因为在实际运行时,窗口大小是固定不变的,所以如果内容过多时,如果使用原生Label,就会在鼠标移上去后显示悬浮提示,对整体外观有所影响。如果内容变化快的话,悬浮提示也会频繁显示,但提示的文本却早已过去,没有提示的意义。
所以此处使用了基于原生控件改造的自定义控件:LLabel。(详见:[C#] (原创)一步一步教你自定义控件——05,Label(原生控件) )
这样通过属性”L_EnableAutoTip=False“,就可以不再显示悬浮提示。
(二)添加属性
1,是否显示“取消”按钮
对于耗时操作,有的时候是可以让用户取消的;而有的时候,则是不能让用户取消。所以需要一个属性去控制是否显示“取消”按钮。
同时,为了美观,在不显示“取消”按钮时,调整窗口高度到合适位置。

2,主进度条模式(进度已知/进度未知)
一些操作的进度是已知的,比如下载进度、复制进度;而有一些操作的的进度是未知的,比如查询操作、调用其他耗时任务等。
针对进度已知还是进度未知,则进度条的样式也需要有相应的改变。

3,窗口标题
当前进度等待窗口的标题

4,默认显示的主进度文本
默认的主进度文本

5,是否显示子进度条
因为大部分时候只需要一个进度,所以子进度条默认是不显示的。而且,子进度条的作用决定了子进度条本身是可以灵活显示/不显示的。
本属性只是提供一个初始化的状态。

6,自定义参数
因为进度等待窗口是一个单独的窗体,而耗时操作也是在本窗口中执行,所以就需要进行数据的交互,而此参数即是为了进行数据的交互。

(三)添加构造函数
为了方便调用,为窗口增加一带参数的构造函数。
这里给大家一个小技巧,在添加构造函数时,可以借用VS的“快速操作和重构...”功能来快速生成构造函数。

(四)添加事件
本篇中执行耗时操作所采用的方法是开一新线程去执行,此方法非常简单且使用方便,所以需要添加一个事件,以让调用者在事件中执行耗时任务。

(五)添加公共方法
因为采用的是线程+事件,所以需要开放一些公共方法,以供调用者在事件实现中使用。
1,更新主进度文本
此方法用于更新主进度文本的内容。

(1),在方法中判断本次更新文本是否与当前显示文本是否一致:if(sMsg!=sLastMainMsg,是为了减少不必要的赋值,减少闪烁,提高性能。(下同将不再赘述)
(2),因为是在新线程中操作控件,所以如果直接操作控件的话,比如给控件赋值,将会提示“线程间操作无效。从不是创建控件'XXX'的线程访问它”的错误,这种情况下需要通过委托的方式去去操作控件。(当然也可以使用不安全代码去解除这种限制,但不推荐使用。)(下同将不再赘述)

2,更新主进度条进度值
此方法用于在主进度条是进度已知时,更新主进度条的进度。


3,更新子进度文本
此方法用于更新子进度文本。


4,更新子进度条进度值
此方法用于在子进度条是进度已知时,更新子进度条的进度。


5,改变子进度条显示状态
因为子进度条是灵活显示的,所以提供本方法去改变进度条的显示状态。


6,改变子进度条样式(进度已知/进度未知)
因为子进度条是灵活显示的,所以提供本方法去改变进度条的样式,是进度已知时样式还是进度未知时样式。
当是进度未知时,要自动启动进度条动画。



7,退出
在事件中实现操作时,可以使用本方法手动结束等待窗口。

(六)事件实现
1,窗口加载事件
在窗口加载时,我们要满足以下条件:
(1),为了更加美观,所以我们不会隐藏掉“关闭”按钮,但是“关闭”按钮会和“取消”按钮功能相冲突,特别是在不能取消时。
所以我们要将“关闭”按钮无效化。主要使用到了系统API:GetSystemMenu和RemoveMenu

(2),如果是进度未知时,要令主进度条开始动画。
(3),开启新线程。此线程即是用来执行耗时任务的,所以要在此线程方法中触发事件委托,以供调用者实现。

所以,加载的实现如下:

2,“取消”按钮事件
点击“取消”时,要满足以下几个条件:
(1),如果主进度条是进度未知,则停止进度条动画。
(2),安全退出。
所以,“取消”按钮的实现如下:

四、效果演示
(1),新建窗体,添加LSwitchButton、Button、Label,如下:

(2),在“进度窗口”点击事件中调用进度等待窗口。

(3),实现耗时任务

(4),运行

五、结束语
本篇所实现的进度等待窗口,技术上很简单,但在美观上、功能上并不弱,而且使用起来也简单。作为日常使用也是足够的。
本篇文章的目的更多的是为了给大家一个使用自定义控件的例子,毕竟自定义控件要在实际的应用中才能体现出价值。
不要被常规思维所束缚,相信自己所掌握的知识。
六、源代码及工程下载
https://files.cnblogs.com/files/lesliexin/05,LProgress.7z
[C#] (原创)进度等待窗口(附:自定义控件的使用)的更多相关文章
- [转载]Winform等待窗口的实现(附源代码)
在开发Winform程序的时候,经常会用到等待窗口(如网络通讯.数据库连接等需要一定时间来执行的操作),这样可以给用户提供更好的体验. 等待窗口的主要功能是一边执行需要等待的操作,一边显示一个等待界面 ...
- WPF中用于嵌入其他进程窗口的自定义控件(AppContainer)
原文:WPF中用于嵌入其他进程窗口的自定义控件(AppContainer) 版权声明:本文为博主原创文章,转载请注明作者和出处 https://blog.csdn.net/ZZZWWWPPP11199 ...
- ASP.NET制作一个简单的等待窗口
前一阵做一个项目,在处理报表的时候时间偏长,客户提出要做出一个等待窗口提示用户等待(页面太久没反映,用户还以为死了呢).在分析这一需求之后,觉得如果要实现像winform应用中的processbar太 ...
- (转载)Android自定义ProgressDialog进度等待框
Android自定义ProgressDialog进度等待框 作者:无缘公子 字体:[增加 减小] 类型:转载 时间:2016-01-11我要评论 这篇文章主要介绍了Android自定义Progress ...
- Qt 使用QLabel、QMovie加载gif图片实现动态等待窗口
新建基于Widget的应用程序,在ui的窗口中添加QLabel,对象名label,调整整个窗口大小. 准备loading.gif图片 Widget.cpp 12345678910111213141 ...
- DEV 等待窗口
DevExpress.Utils.WaitDialogForm dlg = , )); System.Threading.Thread.Sleep(); dlg.Close();
- C# 自定义等待窗口
private SynchronizationContext syncContext = null; public WaitWindow() { InitializeComponent(); sync ...
- Qt 使用QMovie加载gif图片实现动态等待窗口
import sys from PyQt4 import QtGui, QtCore from PyQt4.QtGui import QLabel app = QtGui.QApplication(s ...
- DevExpress21:SplashScreenManager控件实现启动闪屏和等待信息窗口
DevExpress中SplashScreenManager这个控件的主要作用就是显示程序集加载之前的进度条显示和进行耗时操作时候的等待界面. 一.SplashScreenManager控件的使用 1 ...
随机推荐
- vue集成高德地图
vue集成高德地图 前言 二.使用步骤 1.注册高德开发平台 2.vue 结尾 前言 之前玩Thymeleaf的时候玩过高德地图,现在无聊Vue项目也整个地图进去~ 二.使用步骤 1.注册高德开发平台 ...
- Jmeter测试TCP协议
最近做了个项目是TCP协议传输数据,于是马上想试试JMeter测试TCP. 1首先需要下载第三方的TCP插件包ApacheJMeter_tcp.jar,下载步骤请自行百度. 2.下载完重新配置jmet ...
- 面试官问Linux下如何编译C程序,如何回答?为你编译演示
文章来源:嵌入式大杂烩 作者:ZhengNL Windows下常用IDE来编译,Linux下直接使用gcc来编译,编译过程是Linux嵌入式编程的基础,也是嵌入式高频基础面试问题. 一.命令行编译及各 ...
- Java继承的两道实验题目
设计一个表示二维平面上点的类Point,包含有表示坐标位置的Protect类型的成员变量 获取和设置x和y值的public方法 package classwork_6; public class Po ...
- linux上的PXE装机服务的搭建
PXE 先安装一下依赖服务 yum -y install vsftpd dhcp tftp syslinux tftp-server cd /var/ftp/pub/ mkdir dvd 设置权限 c ...
- Image Inpainting with Learnable Bidirectional Attention Maps
Image Inpainting with Learnable Bidirectional Attention Maps pytorch 引言 部分卷积(PConv)的缺陷: 1 将含有1个有效值像素 ...
- CentOS下配置VNC
配置桌面 # 安装gnome桌面环境 yum groupinstall Desktop -y # 安装中文语言支持包(可选) yum groupinstall 'Chinese Support' -y ...
- Springboot结合Jpa的外键使用
当我们写项目的时候,总有些奇奇怪怪的理由,非让你连表查询,其实最好的就是什么都不连,数据库完全解耦 但我们还是要学习下Jpa怎么根据外键查询 (这里说下Jpa+springboot的感觉,刚开始就感觉 ...
- 2014.04.28基于CPLD的LCOS场序彩色视频控制器设计
基于CPLD的LCOS场序彩色视频控制器设计 作者:宋丹娜,代永平,刘艳艳,商广辉 发表刊物:液晶与显示,2009 学习时间:2014.04.28 文章讲述了-- (和上一篇论文有些相似之处) 1. ...
- PyQt(Python+Qt)学习随笔:Designer中的QDialogButtonBox的clicked信号参数QAbstractButton *解决办法
一.引言 QDialogButtonBox本身只提供4种信号,分别是accepted.rejected.clicked和helpRequested,在<PyQt(Python+Qt)学习随笔:D ...