WinForm下的loading框的实现

前言:在项目使用C/S模式情况下,由于需要经常进行数据的刷新,如果直接进行刷新,会有一个等待控件重画的过程,非常的不友好,因此在这里添加一个loading框进行等待显示。

实现:在经过多方面查询资料,终于是实现了一个完整的loading框程序,这里主要解决在多次点击查询按钮或者加载数据时出现的:执行 CreateHandle() 时无法调用值 Close()或者无法访问已释放的对象或者在创建窗口句柄之前,不能在控件上调用 Invoke 或 BeginInvoke。这三个问题困扰我很久,最终通过不断的调试,将其解决,话不多说,直接上代码。


1.下面类为loading框帮助类,在实际调用过程中,使用该类调用相关函数即可。

 1 class LoadingHelper
 2 {
 3         #region 相关变量定义
 4         /// <summary>
 5         /// 定义委托进行窗口关闭
 6         /// </summary>
 7         private delegate void CloseDelegate();
 8         private static LoaderForm loadingForm;
 9         private static readonly Object syncLock = new Object();  //加锁使用
10 
11         #endregion
12 
13         private LoadingHelper()
14         {
15 
16         }
17 
18         /// <summary>
19         /// 显示loading框
20         /// </summary>
21         public static void ShowLoadingScreen()
22         {
23             // Make sure it is only launched once.
24             if (loadingForm != null)
25                 return;
26             Thread thread = new Thread(new ThreadStart(LoadingHelper.ShowForm));
27             thread.IsBackground = true;
28             thread.SetApartmentState(ApartmentState.STA);
29             thread.Start();
30 
31         }
32 
33         /// <summary>
34         /// 显示窗口
35         /// </summary>
36         private static void ShowForm()
37         {
38             if (loadingForm != null)
39             {
40                 loadingForm.closeOrder();
41                 loadingForm = null;
42             }
43             loadingForm = new LoaderForm();
44             loadingForm.TopMost = true;
45             loadingForm.ShowDialog();
46         }
47 
48         /// <summary>
49         /// 关闭窗口
50         /// </summary>
51         public static void CloseForm()
52         {
53             Thread.Sleep(50); //可能到这里线程还未起来,所以进行延时,可以确保线程起来,彻底关闭窗口
54             if (loadingForm != null)
55             {
56                 lock (syncLock)
57                 {
58                     Thread.Sleep(50);  
59                     if (loadingForm != null)
60                     {
61                         Thread.Sleep(50);  //通过三次延时,确保可以彻底关闭窗口
62                         loadingForm.Invoke(new CloseDelegate(LoadingHelper.CloseFormInternal));
63                     }
64                 }
65             }
66         }
67 
68         /// <summary>
69         /// 关闭窗口,委托中使用
70         /// </summary>
71         private static void CloseFormInternal()
72         {
73 
74             loadingForm.closeOrder();
75             loadingForm = null;
76 
77         }
78 
79     }                                                                                                                                        

2.LoaderForm窗体具体代码如下。

 1 public partial class LoaderForm : Form
 2 {
 3 
 4         public LoaderForm()
 5         {
 6             InitializeComponent();
 7         }
 8 
 9         /// <summary>
10         /// 关闭命令
11         /// </summary>
12         public void closeOrder()
13         {
14             if (this.InvokeRequired)
15             {  
16                 //这里利用委托进行窗体的操作,避免跨线程调用时抛异常,后面给出具体定义
17                 CONSTANTDEFINE.SetUISomeInfo UIinfo = new CONSTANTDEFINE.SetUISomeInfo(new Action(() =>
18                 {
19                     while (!this.IsHandleCreated)
20                     {
21                         ;
22                     }
23                     if (this.IsDisposed)
24                         return;
25                     if (!this.IsDisposed)
26                     {
27                         this.Dispose();
28                     }
29 
30                 }));
31                 this.Invoke(UIinfo);
32             }
33             else
34             {
35                 if (this.IsDisposed)
36                     return;
37                 if (!this.IsDisposed)
38                 {
39                     this.Dispose();
40                 }
41             }
42         }
43 
44         private void LoaderForm_FormClosing(object sender, FormClosingEventArgs e)
45         {
46             if (!this.IsDisposed)
47             {
48                 this.Dispose(true);
49             }
50 
51         }
52 
53 }        

对LoaderForm窗体相关说明:

1.public delegate void SetUISomeInfo(); //定义一个委托,处理UI相关信息问题。

2.LoaderForm窗体上放置了一个label,将其AutoSize属性设置为false,并将LoaderForm的TransparencyKey属性设置为Transparent(这样设置避免在加载loading框时出现背景,loading.gif最好选择透明背景的图片)。

至此,一个完整的loading框,已经搞定。


by Shawn Chen,2017.7.2日,晚。

posted @ 2017-07-02 22:47  developer_chan  阅读(15310)  评论(4编辑  收藏  举报