在WEB上,我们在需要进行大数据或复杂逻辑处理时,由于耗时较长,一般我们会在处理过程中的页面上显示一个半透明的遮罩层,上面放个图标或提示:正在处理中…等字样,这样用户体验就比较好了,然而如果在Winform客户端程序,通常遮罩层的处理就显得不那么简单或不那么好看,而我今天要说明的是,我实现的这个Winform通用遮罩层,却可以实现类似WEB上的遮罩层,既可以透明,而且还可以显示动态图片以及文字,那如何实现的呢,我现在一一讲解。

首先要明确我们要实现的效果:透明+动态图标+文字

透明:这个简单,只需要将窗体的Opacity设为100%以下的值就可以了,这里我采用85%;

动态图标:这个相对复杂一些,因为Winform目前没有现成的支持直接显示动图的控件,但幸好有一个组件ImageAnimator支持逐帧动画,我们只需要将图片绑定到ImageAnimator的Animate方法上(即:ImageAnimator.Animate(m_Image,EventHandler委托);),然后重写窗体的OnPaint即可,具体的代码实现见下面公布的源码。

文字:这个简单,放在一个Label控件即可

还有为了能够让图标与文字在相对的位置(即不论大小)保持居中,我这里采用了一个TableLayoutPanel,分成两行,上行放置Label,并设为居中,下行放置Panel,提供绘制动图的区域。

完整代码实现如下(部份代码参考网络上它人的文章):

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Reflection;
using System.Threading;
using System.Threading.Tasks;namespace TEMS
{public partial class FrmProcessing : Form{private static Image m_Image = null;private EventHandler evtHandler = null;private ParameterizedThreadStart workAction = null;private object workActionArg = null;private Thread workThread = null;public string Message{get{return lbMessage.Text;}set{lbMessage.Text = value;}}public bool WorkCompleted = false;public Exception WorkException{ get; private set; }public void SetWorkAction(ParameterizedThreadStart workAction, object arg){this.workAction = workAction;this.workActionArg = arg;}public FrmProcessing(string msg){InitializeComponent();this.Message = msg;}protected override  void OnPaint(PaintEventArgs e){base.OnPaint(e);if (m_Image != null){//获得当前gif动画下一步要渲染的帧。UpdateImage();//将获得的当前gif动画需要渲染的帧显示在界面上的某个位置。int x = (int)(panImage.ClientRectangle.Width - m_Image.Width) / 2;int y = 0;//e.Graphics.DrawImage(m_Image, new Rectangle(x, y, m_Image.Width, m_Image.Height));panImage.CreateGraphics().DrawImage(m_Image, new Rectangle(x, y, m_Image.Width, m_Image.Height));}if (this.WorkCompleted){this.Close();}}private void FrmProcessing_Load(object sender, EventArgs e){if (this.Owner != null){this.StartPosition = FormStartPosition.Manual;this.Location = new Point(this.Owner.Left, this.Owner.Top);//MessageBox.Show(string.Format("X={0},Y={1}", this.Owner.Left, this.Owner.Top));this.Width = this.Owner.Width;this.Height = this.Owner.Height;}else{Rectangle screenRect = Screen.PrimaryScreen.WorkingArea;this.Location = new Point((screenRect.Width - this.Width) / 2, (screenRect.Height - this.Height) / 2);}//为委托关联一个处理方法evtHandler = new EventHandler(OnImageAnimate);if (m_Image == null){Assembly assy = Assembly.GetExecutingAssembly();//获取要加载的gif动画文件m_Image = Image.FromStream(assy.GetManifestResourceStream(assy.GetName().Name + ".Resources.loading2.gif"));}//调用开始动画方法BeginAnimate();}//开始动画方法private void BeginAnimate(){if (m_Image != null){//当gif动画每隔一定时间后,都会变换一帧,那么就会触发一事件,该方法就是将当前image每变换一帧时,都会调用当前这个委托所关联的方法。ImageAnimator.Animate(m_Image, evtHandler);}}//委托所关联的方法private void OnImageAnimate(Object sender, EventArgs e){//该方法中,只是使得当前这个winform重绘,然后去调用该winform的OnPaint()方法进行重绘)this.Invalidate();}//获得当前gif动画的下一步需要渲染的帧,当下一步任何对当前gif动画的操作都是对该帧进行操作)private void UpdateImage(){ImageAnimator.UpdateFrames(m_Image);}//关闭显示动画,该方法可以在winform关闭时,或者某个按钮的触发事件中进行调用,以停止渲染当前gif动画。private void StopAnimate(){m_Image = null;ImageAnimator.StopAnimate(m_Image, evtHandler);}private void FrmProcessing_Shown(object sender, EventArgs e){if (this.workAction != null){workThread = new Thread(ExecWorkAction);workThread.IsBackground = true;workThread.Start();}}private void ExecWorkAction(){try{var workTask = new Task((arg) =>{this.workAction(arg);},this.workActionArg);workTask.Start();Task.WaitAll(workTask);}catch (Exception ex){this.WorkException = ex;}finally{this.WorkCompleted = true;}}}
}

以下是自动生成的代码:

namespace TEMS
{partial class FrmProcessing{/// <summary>/// Required designer variable./// </summary>private System.ComponentModel.IContainer components = null;/// <summary>/// Clean up any resources being used./// </summary>/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>protected override void Dispose(bool disposing){if (disposing && (components != null)){components.Dispose();}base.Dispose(disposing);}#region Windows Form Designer generated code/// <summary>/// Required method for Designer support - do not modify/// the contents of this method with the code editor./// </summary>private void InitializeComponent(){this.tableLayoutPanel1 = new System.Windows.Forms.TableLayoutPanel();this.lbMessage = new System.Windows.Forms.Label();this.panImage = new System.Windows.Forms.Panel();this.tableLayoutPanel1.SuspendLayout();this.SuspendLayout();// // tableLayoutPanel1// this.tableLayoutPanel1.ColumnCount = 1;this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle());this.tableLayoutPanel1.Controls.Add(this.lbMessage, 0, 0);this.tableLayoutPanel1.Controls.Add(this.panImage, 0, 1);this.tableLayoutPanel1.Dock = System.Windows.Forms.DockStyle.Fill;this.tableLayoutPanel1.Location = new System.Drawing.Point(0, 0);this.tableLayoutPanel1.Name = "tableLayoutPanel1";this.tableLayoutPanel1.RowCount = 2;this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 50F));this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 50F));this.tableLayoutPanel1.Size = new System.Drawing.Size(582, 318);this.tableLayoutPanel1.TabIndex = 1;// // lbMessage// this.lbMessage.BackColor = System.Drawing.Color.Transparent;this.lbMessage.Dock = System.Windows.Forms.DockStyle.Fill;this.lbMessage.Font = new System.Drawing.Font("微软雅黑", 14.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));this.lbMessage.Location = new System.Drawing.Point(3, 0);this.lbMessage.Name = "lbMessage";this.lbMessage.Padding = new System.Windows.Forms.Padding(0, 0, 0, 30);this.lbMessage.Size = new System.Drawing.Size(576, 159);this.lbMessage.TabIndex = 1;this.lbMessage.Text = "lbMessage\r\nadsfadsf";this.lbMessage.TextAlign = System.Drawing.ContentAlignment.BottomCenter;// // panImage// this.panImage.Dock = System.Windows.Forms.DockStyle.Fill;this.panImage.Location = new System.Drawing.Point(3, 162);this.panImage.Name = "panImage";this.panImage.Size = new System.Drawing.Size(576, 153);this.panImage.TabIndex = 2;// // FrmProcessing// this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F);this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;this.BackColor = System.Drawing.SystemColors.Control;this.ClientSize = new System.Drawing.Size(582, 318);this.Controls.Add(this.tableLayoutPanel1);this.Cursor = System.Windows.Forms.Cursors.WaitCursor;this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.None;this.Name = "FrmProcessing";this.Opacity = 0.85D;this.StartPosition = System.Windows.Forms.FormStartPosition.Manual;this.Text = "FrmProcessing";this.Load += new System.EventHandler(this.FrmProcessing_Load);this.Shown += new System.EventHandler(this.FrmProcessing_Shown);this.tableLayoutPanel1.ResumeLayout(false);this.ResumeLayout(false);}#endregionprivate System.Windows.Forms.TableLayoutPanel tableLayoutPanel1;private System.Windows.Forms.Label lbMessage;private System.Windows.Forms.Panel panImage;}
}

代码中SetWorkAction方法是用来设置异步需要处理的委托方法,在窗体显示出来后(FrmProcessing_Shown),创建新线程,用以处理耗时的逻辑代码段,其中有一个WorkCompleted属性,这个主要是表明处理耗时的逻辑代码已完成(不论是否报错),在窗体重绘时(OnPaint),会持续判断该值是否为true,若为true则关闭当前窗口。

另之所以没重写Panel的OnPaint方法,原因是虽然可以显示动图,但由于局部重绘,造成动图出现闪屏,所以仍需要采用窗体重绘

为了便于通用,我还定义了一个通用方法,专门用来显示遮罩层窗体,方法定义如下:

public static class Common{public static void ShowProcessing(string msg, Form owner, ParameterizedThreadStart work, object workArg = null){FrmProcessing processingForm = new FrmProcessing(msg);dynamic expObj = new ExpandoObject();expObj.Form = processingForm;expObj.WorkArg = workArg;processingForm.SetWorkAction(work, expObj);processingForm.ShowDialog(owner);if (processingForm.WorkException != null){throw processingForm.WorkException;}}}

现在使用就很简单了,如下:

Common.ShowProcessing("正在处理中,请稍候...", this, (obj) =>
{//这里写处理耗时的代码,代码处理完成则自动关闭该窗口
},null);


大家可以将上述代码直接复制到新建的窗体中,即可立即使用,上述代码若有不足之处,还请大家评论并指出,谢谢!

Winform 通用遮罩层相关推荐

  1. Winform应用程序实现通用遮罩层二

    之前先后发表过:<Winform应用程序实现通用遮罩层>.<Winform应用程序实现通用消息窗口>,这两款遮罩层其实都是基于弹出窗口的,今天为大家分享一个比较简单但界面相对友 ...

  2. C#实现Winform自定义半透明遮罩层

    在网页中通过div+css实现半透明效果不难,今天我们看看一种在winfrom中实现的方法: 效果图如下,正常时: 显示遮罩层时: 自定义遮罩层控件的源码如下: View Code using Sys ...

  3. js遮罩层以及移动端的上拉框

    今天发一个之前写的移动端的项目,主要是讲一下遮罩层的应用,以及顺带提一下移动开发的一些事情.首先按钮点击弹出遮罩层这个大家很熟悉了,这里还是给大家提供一份代码,跟通用的没太大区别,主要讲一下方法: $ ...

  4. CSS遮罩层:hover状态丢失及解决方案

    CSS遮罩层,顾名思义就是在div上,再"铺"一层半透明的div.在hover时,亦可进一步改变该遮罩层的色彩和透明度.我们可以通过css定位和背景色实现. CSS遮罩层实现及ho ...

  5. css3全屏遮罩层,css3 引导遮罩层

    https://blog.csdn.net/tangtang5963/article/details/51276560 要实现遮罩层和部分区域高亮显示,这里的思路是应用了元素的border属性,将元素 ...

  6. html中鼠标经过遮罩消失,CSS遮罩层:hover状态丢失及解决方案

    CSS遮罩层,顾名思义就是在div上,再"铺"一层半透明的div.在hover时,亦可进一步改变该遮罩层的色彩和透明度.我们可以通过css定位和背景色实现. CSS遮罩层实现及ho ...

  7. css3新增选择器、伪元素、隐藏元素的方法、visibility: hidden与display:none;的区别 、遮罩层效果、​ 三级菜单制作、选项卡制作——css3知识点总结

    目录 css3新增选择器 兄弟选择器 属性选择器 伪类选择器 其他伪类选择器 类元素选择器 直接选择器 否定选择器 伪元素 :after清除浮动 :before和:after 用来写小三角形 首字母 ...

  8. DIV遮罩层、弹框、设置颜色、边框颜色设置等功能实现

    文章目录 DIV遮罩层.弹框.设置颜色.边框颜色设置等功能实现 一.DIV是什么? 二.功能实现 1.静态页面 2.弹框 3.边框设置 三.参考代码 DIV遮罩层.弹框.设置颜色.边框颜色设置等功能实 ...

  9. css 定位及遮罩层小技巧

    relative定位:相对它自己的正常位置的定位. fixed定位:fixed定位是指元素的位置相对于浏览器窗口是固定位置,即使窗口是滚动的它也不会滚动,且fixed定位使元素的位置与文档流无关,因此 ...

最新文章

  1. 国内ntp服务器ip地址
  2. 017-封装-OC笔记
  3. RHEL5系统下故障处理方法
  4. WCF学习笔记之可靠会话
  5. flink source 同步_如何生成 Flink 作业的交互式火焰图?
  6. django 1.8 官方文档翻译:9-1-4 格式本地化
  7. python和c先学哪个-python和c,应该先学哪个?
  8. 构建与服务器的JDK版本不同,导致服务器不能工作
  9. MSDN URL 重写
  10. vue实现导入导出xlsx exel的数据渲染到table表格上面,表格数据改动然后再导出数据
  11. SQLyog安装地址
  12. USB 3.0规范中译本 第7章 链路层
  13. Apple 开发者论坛新功能体验
  14. Java线程强制执行
  15. 众多快递中驿站代收的单号怎么查询、筛选的
  16. P2327 [SCOI2005]扫雷 - 模拟
  17. 阿里巴巴P8架构师手码SpringCloud笔记,看完不走弯路
  18. openstackAZ配置
  19. 从0开始编程学习历程Day1
  20. P2P技术基础: UDP打洞原理

热门文章

  1. Python+MXNet+GluonCV+Cuda安装
  2. 计算机英语刘艺课件,计算机英语刘艺 王春生Unit1.ppt
  3. 如何批量生成GS1-128条码
  4. 手动制做字体子集(字体文件裁剪、抽取、提取,特别适用处理少量繁体异体字)
  5. 10分钟看懂Docker和K8S,docker k8s 区别(生动形象,清晰易懂)
  6. 嵌入式linux使用ros,ARM平台基于嵌入式Linux部署ROS
  7. vue 翻牌器 记录下
  8. SNS社交平台的核心技术架构
  9. html查看器 小米8,小米文档查看器app
  10. HBU-NNDL 实验六 卷积神经网络(2)基础算子