首页 > 编程语言 >Winform应用程序实现通用消息窗口

Winform应用程序实现通用消息窗口

时间:2022-09-20 11:56:30浏览次数:80  
标签:10 窗口 System FRM 耗时 应用程序 labMessage Waitting Winform

记得我之前发表过一篇文章《Winform应用程序实现通用遮罩层》,是实现了透明遮罩的消息窗口,功能侧重点在动图显示+消息提醒,效果看上去比较的炫,而本篇我又来重新设计通用消息窗口,功能重点在于消息提醒、进度报告,当然如果大家时间,可以将两种相结合,那样就会更完美了,我这里仍是以实现功能为主,由于代码相对简单,我就直接贴上所有代码,大家可以直接复制到本地测试,若发现问题可自行改正或反馈给我,我来完善,谢谢!

?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Text; using System.Threading; using System.Windows.Forms;   namespace WindowsFormsApplication1 {     /// <summary>     /// 等待窗口:用于处理耗时工作时,友好显示消息窗口     /// 作者:Zuowenjun     /// 日期:2016-1-29     /// 网址:http://www.zuowenjun.cn     /// </summary>     public partial class FRM_Waitting : Form     {         private SynchronizationContext formContext;           public string Message         {             get { return labMessage.Text; }             set { labMessage.Text = value; }         }           public Action<WaittingForWorkObject> WorkAction { get; set; }           public object WorkActionParam { get; set; }           public Exception WorkException { get; private set; }           public class WaittingForWorkObject         {             private SendOrPostCallback UpdateMessageAction = null;             public SynchronizationContext Context { get; private set; }               public object UserData { get; private set; }               public void UpdateMessage(string msg)             {                 this.Context.Post(UpdateMessageAction, msg);             }               public WaittingForWorkObject(FRM_Waitting parentForm)             {                 this.Context = parentForm.formContext;                 this.UserData = parentForm.WorkActionParam;                 this.UpdateMessageAction = delegate(object o)                 {                     parentForm.Message = o.ToString();                 };             }         }             public static void WaittingForWork(Action<WaittingForWorkObject> workAction, object workParam = null, string text = "请稍候", string message = "系统处理中,请稍候...")         {             var waittingForm = new FRM_Waitting(text, message, workAction, workParam);             waittingForm.ShowDialog();             if (waittingForm.WorkException != null)             {                 throw waittingForm.WorkException;             }           }           public FRM_Waitting()         {             InitializeComponent();         }           public FRM_Waitting(string text, string message, Action<WaittingForWorkObject> workAction, object workParam = null)             : this()         {             this.Text = text;             this.Message = message;             this.WorkAction = workAction;             this.WorkActionParam = workParam;         }           private void FRM_Waitting_Load(object sender, EventArgs e)         {           }           private void FRM_Waitting_Shown(object sender, EventArgs e)         {             formContext = SynchronizationContext.Current;             if (WorkAction != null)             {                 Thread workThread = new Thread(DoWork);                 workThread.IsBackground = true;                 workThread.Start();             }         }           private void DoWork()         {             try             {                 var wfObject = new WaittingForWorkObject(this);                 WorkAction(wfObject);             }             catch (Exception ex)             {                 WorkException = ex;             }             formContext.Send(delegate(object o) { this.Close(); }, null);         }           } }

以下是系统自动生成的代码:

+ View Code?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 namespace WindowsFormsApplication1 {     partial class FRM_Waitting     {         /// <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.labMessage = new System.Windows.Forms.Label();             this.SuspendLayout();             //             // labMessage             //             this.labMessage.Dock = System.Windows.Forms.DockStyle.Fill;             this.labMessage.Font = new System.Drawing.Font("宋体", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));             this.labMessage.Location = new System.Drawing.Point(0, 0);             this.labMessage.Name = "labMessage";             this.labMessage.Padding = new System.Windows.Forms.Padding(5);             this.labMessage.Size = new System.Drawing.Size(453, 125);             this.labMessage.TabIndex = 0;             this.labMessage.Text = "Message";             this.labMessage.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;             this.labMessage.UseWaitCursor = true;             //             // FRM_Waitting             //             this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F);             this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;             this.ClientSize = new System.Drawing.Size(453, 125);             this.ControlBox = false;             this.Controls.Add(this.labMessage);             this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle;             this.Name = "FRM_Waitting";             this.ShowIcon = false;             this.ShowInTaskbar = false;             this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent;             this.Text = "FRM_Waitting";             this.UseWaitCursor = true;             this.Load += new System.EventHandler(this.FRM_Waitting_Load);             this.Shown += new System.EventHandler(this.FRM_Waitting_Shown);             this.ResumeLayout(false);           }           #endregion           private System.Windows.Forms.Label labMessage;     } }

上述代码比较简单,我这里对消息窗口的实现原理作一个简要的说明:

1.将耗时处理逻辑代码封装到一个委托中(Aciton<FRM_Waitting.WaittingForWorkObject>);

2.获取当前同步上下文并保存,以便可以跨线程操作UI;

3.创建并运行一个后台线程,同时将该线程指定到DoWork(工作方法);

4.在DoWork方法中实例化WaittingForWorkObject对象,并传给1中委托,然后执行委托,这样耗时的操作都在后台线程中处理了;

5.在DoWork方法使用try catch捕获可能存在的异常,若发生异常则保存到WorkException属性中;

6.执行完成后(无论是否报错),通过同上下文发送关闭消息窗口指令,使消息窗口关闭;

7.在静态方法WaittingForWork中判断WorkException属性是否不为空,若不为空则重新抛出错误,这样主线程就知道发生了什么异常;

 说明:为了能够兼容.NET 2.0及以上版本,代码中采用了匿名方法,而非Lambada表达式,实际使用时则可以任意选择,下面的测试示例中均提供了新旧两种代码写法,以供大家比较。

以下是各种测试示例:

?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 /// <summary> /// 测试:普通显示一个消息窗口 /// </summary> private void Test1() {     //旧方式(兼容.NET2.0及以上)     FRM_Waitting.WaittingForWork(delegate(FRM_Waitting.WaittingForWorkObject o)     {         //在这里面写耗时处理逻辑代码,以下是模拟耗时         Thread.Sleep(10 * 1000);     });       //新方式(.NET4.0及以上)     //FRM_Waitting.WaittingForWork((o) =>     //{         //在这里面写耗时处理逻辑代码,以下是模拟耗时     //    Thread.Sleep(10 * 1000);     //});   }

效果如下:

 

?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 /// <summary> /// 测试:普通显示一个消息窗口,并自定义提示消息并窗口标题 /// </summary> private void Test1_1() {     //旧方式(兼容.NET2.0及以上)     FRM_Waitting.WaittingForWork(delegate(FRM_Waitting.WaittingForWorkObject o)     {         //在这里面写耗时处理逻辑代码,以下是模拟耗时         Thread.Sleep(10 * 1000);     },null,"客官请稍候","客官,店小二正在为您拼命处理中,请稍等片刻...");       //新方式(.NET4.0及以上)     //FRM_Waitting.WaittingForWork((o) =>     //{         //在这里面写耗时处理逻辑代码,以下是模拟耗时     //    Thread.Sleep(10 * 1000);     //},null,"客官请稍候","客官,店小二正在为您拼命处理中,请稍等片刻...");   }

效果如下:

 

?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 /// <summary> /// 测试:普通显示一个消息窗口,并在后台线程中抛出错误,前台显示错误信息 /// </summary>  private void Test1_2() {      try      {          //旧方式(兼容.NET2.0及以上)          //FRM_Waitting.WaittingForWork(delegate(FRM_Waitting.WaittingForWorkObject o)          //{          //    //在这里面写耗时处理逻辑代码,以下是模拟耗时          //    Thread.Sleep(10 * 1000);          //    throw new Exception("这里后台线程里抛出的错误!");          //});            //新方式(.NET4.0及以上)          FRM_Waitting.WaittingForWork((o) =>          {             //在这里面写耗时处理逻辑代码,以下是模拟耗时              Thread.Sleep(10 * 1000);              throw new Exception("这里后台线程里抛出的错误!");          });        }      catch(Exception ex)      {          MessageBox.Show("发生异常:" + ex.Message);      } }

效果如下:

 

?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 /// <summary> /// 测试:在消息窗口上显示加载进度 /// </summary> private void Test2() {       //旧方式(兼容.NET2.0及以上)     //FRM_Waitting.WaittingForWork(delegate(FRM_Waitting.WaittingForWorkObject o)     //{             //在这里面写耗时处理逻辑代码,以下是模拟耗时     //    for (int i = 1; i <= 10; i++)     //    {     //        Thread.Sleep(1000);     //        o.UpdateMessage(string.Format("共{0}项,当前已加载{1}项", 10, i));     //    }       //});       //新方式(.NET4.0及以上)     FRM_Waitting.WaittingForWork((o) =>     {         //在这里面写耗时处理逻辑代码,以下是模拟耗时         for (int i = 1; i <= 10; i++)         {             Thread.Sleep(1000);             o.UpdateMessage(string.Format("共{0}项,当前已加载{1}项", 10, i));         }       });   }

效果如下:

 

?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 /// <summary> /// 测试:在消息窗口上显示加载进度,并同时在主窗口(非消息窗口都可以)上更新控件内容 /// </summary> private void Test3() {       //旧方式(兼容.NET2.0及以上)     FRM_Waitting.WaittingForWork(delegate(FRM_Waitting.WaittingForWorkObject o)     {         //在这里面写耗时处理逻辑代码,以下是模拟耗时         for (int i = 1; i <= 10; i++)         {             Thread.Sleep(1000);             o.UpdateMessage(string.Format("共{0}项,当前已加载{1}项", 10, i));             o.Context.Send(delegate(object d) { this.listBox1.Items.Add(d); }, string.Format("共{0}项,当前已加载{1}项", 10, i));         }       });       //新方式(.NET4.0及以上)     //FRM_Waitting.WaittingForWork((o) =>     //{         //在这里面写耗时处理逻辑代码,以下是模拟耗时     //    for (int i = 1; i <= 10; i++)     //    {     //        Thread.Sleep(1000);     //        o.UpdateMessage(string.Format("共{0}项,当前已加载{1}项", 10, i));     //        o.Context.Send(d => this.listBox1.Items.Add(d), string.Format("共{0}项,当前已加载{1}项", 10, i));     //    }       //});   }

效果如下:

 

看完上面的测试效果,大家觉得如何,能否满足你的日常要求呢,我认为基本都可以满足的,当然如果发现更多的情况,欢迎在下方评论留言。

 

 

出处:https://www.cnblogs.com/zuowj/p/5169241.html

标签:10,窗口,System,FRM,耗时,应用程序,labMessage,Waitting,Winform
From: https://www.cnblogs.com/mq0036/p/16710540.html

相关文章

  • 两种实现Winform程序的多语言支持的解决方案
    因公司业务需要,需要将原有的ERP系统加上支持繁体语言,但不能改变原有的编码方式,即:普通程序员感受不到编码有什么不同。经过我与几个同事的多番沟通,确定了以下两种方案:方案......
  • 使用 Amplication 缩短 Node.js 应用程序的上线时间
    使用Amplication缩短Node.js应用程序的上线时间AmplicationStack使用任何技术开发任何应用程序都是一个复杂的过程。我们必须考虑很多事情,比如架构、使用哪些技术......
  • Winform自定义窗体标题栏样式
    最近在编写C/S结构应用程序时,感觉窗体的标题栏样式太死板了,标题文字不能更改大小、颜色、字体等,按钮不能隐藏等问题,在网上也查找了许多相关的资料,没有找到合适的解决方案,......
  • window 对象的常见事件-[页面窗口加载事件]
    window对象的常见事件-[页面/窗口加载事件](1)window.onload=function(){}或者window.addEventListener("load",function(){});window.onload是窗口(页面)加载......
  • 如何使用Vue原生组件编译应用程序主题?这个工具不要错过
    KendoUI致力于新的开发,来满足不断变化的需求。KendoUIforVue使用旨在提高性能和丰富用户体验的Vue组件,帮助开发人员构建下一代应用程序。它是为Vue技术框架提供可用的K......
  • Magnet for mac(窗口辅助管理工具)中文版
    magnet mac版是一款运行在苹果电脑上的一款优秀的窗口大小控制工具,拖拽窗口到屏幕边缘可以自动半屏,全屏或者四分之一屏幕,还可以设定快捷键完成分屏。这款专业的窗口管理......
  • Electron学习(四)之应用程序打包
    如何将应用程序打包(Win)1、关于package.js文件详解完整实例如下:"build":{"productName":"xxxx",//项目名这也是生成的exe文件的前缀名"appId":"com.leon.x......
  • rust执行cmd命令隐藏窗口
    https://blog.csdn.net/weixin_35894173/article/details/112282032https://rustcc.cn/article?id=f1630b61-4637-4e80-8414-8a921af50d68主要原理是,通过函数creation_fl......
  • SQLZOO记录 2:窗口函数
    SQL窗口函数包括LAG、LEAD、RANK和NTILE。这些函数在行的“窗口”上运行——通常是表中某种意义上相邻的行。9-WindowfunctionsShowthelastName,partyandv......
  • Pega 应用程序中的辅助文本颜色/字体更改
    Pega应用程序中的辅助文本颜色/字体更改你好,在这个故事中,我们将看到如何在Pega中更改HelperText的颜色、字体大小、字体粗细。在任何部分中,通过单击属性上的齿轮......