为了给用户提供更好的体验,读取数据库等程序需要长时间来执行的操作,需要弹出一个等待界面。可以一边执行需要等待的操作,一边显示一个等待界面。当执行完毕时等待界面消失。用户可以提前取消操作,还可以设置操作的最大等待时间,若超过指定时间仍没完成操作可结束当前操作。
如图所示:
从上图可以看到等待窗体是透明的。
首先新一个Windows窗体应用项目,包含两个窗体:等待窗体LoadForm和主窗体MainForm。
等待窗体界面加入一个pictureBox控件并设置其SizeMode属性值为AutoSize,让图片框能根据图片大小自动伸缩,然后添加一张没有背景的GIF图片;再加入2个Label控件用于显示提示信息(可以自定义)和操作时间;再加入一个Button控件用于取消操作。
对窗体的FormBorderStyle属性设置为无边框,StartPosition设置为显示到父窗体中间,ShowInTaskbar设置为不在任务栏显示,最重点的是TransparencyKey属性,用于设置窗体透明区域颜色,我们把他设置为窗体背景色,这样呈现出来的就是一个透明的窗体了。
如图:
在等待窗口代码区添加如下代码:
Public Class LoadForm
Private _MaxWaitTime As Integer
Private _WaitTime As Integer
Private _CancelEnable As Boolean
Private _AsyncResult As IAsyncResult
Private _method As MethodInvoker
Public Property Message As String
Public Property TimeSpan As Integer
Public Sub New(ByVal method As MethodInvoker, ByVal maxWaitTime As Integer, ByVal waitMessage As String, ByVal cancelEnable As Boolean, ByVal timerVisable As Boolean)
maxWaitTime *= 1000
Initialize(method, maxWaitTime, waitMessage, cancelEnable, timerVisable)
End Sub
Private Sub Initialize(ByVal method As MethodInvoker, ByVal maxWaitTime As Integer, ByVal waitMessage As String, ByVal cancelEnable As Boolean, ByVal timerVisable As Boolean)
InitializeComponent()
'无边框
Me.FormBorderStyle = FormBorderStyle.None
'起始位于父窗体中间
Me.StartPosition = FormStartPosition.CenterParent
'不在任务栏显示
Me.ShowInTaskbar = False
'窗体透明区域颜色为窗体背景色
Me.TransparencyKey = Me.BackColor
Me.labMessage.Text = waitMessage
TimeSpan = 500
Message = String.Empty
_CancelEnable = cancelEnable
_MaxWaitTime = maxWaitTime
_WaitTime = 0
_method = method
Me.LikCancel.Visible = _CancelEnable
Me.labTimer.Visible = timerVisable
Me.Timer1.Interval = TimeSpan
Me.Timer1.Start()
End Sub
Private Sub LikCancel_LinkClicked(sender As Object, e As LinkLabelLinkClickedEventArgs) Handles LikCancel.LinkClicked
Me.Message = "您结束了当前操作!"
Me.Close()
End Sub
Private Sub Timer1_Tick(sender As Object, e As EventArgs) Handles Timer1.Tick
_WaitTime += TimeSpan
Me.labTimer.Text = String.Format("{0}秒", _WaitTime / 1000)
If Not Me._AsyncResult.IsCompleted Then
If _WaitTime > _MaxWaitTime Then
_method.EndInvoke(_AsyncResult)
Message &= String.Format("处理数据超时{0}秒,结束当前操作!", _MaxWaitTime / 1000)
Me.Close()
End If
Else
Me.Message = String.Empty
Me.Close()
End If
End Sub
Private Sub LoadForm_Shown(sender As Object, e As EventArgs) Handles Me.Shown
_AsyncResult = _method.BeginInvoke(Nothing, Nothing)
End Sub
End Class
再到主窗体MainForm里添加调用等待窗体的代码:
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim f As LoadForm = New LoadForm(Sub()
Threading.Thread.Sleep(9000)
MessageBox.Show("OK")
End Sub, 5, "Plase Wait...", True, True)
f.ShowDialog(Me)
Dim Res As String = f.Message
If Not String.IsNullOrEmpty(Res) Then
MessageBox.Show(Res)
End If
f.Dispose()
End Sub
代码的关键处是用到了委托机制,而且最关键是异步调用委托(BeginInvoke和EndInvoke),为了方便,这里使用.Net Framework中提供的预定义委托MethodInvoker,内置的委托还有Action、Func、Predicate等。用到委托的时候建议尽量使用这些委托类型,而不是在代码中定义更多的委托类型。这样既可以减少系统中的类型数目,又可以简化代码。 关联委托方法时使用了Lambda 表达式,其实就是一个没有方法名的方法,可以有返回值。 遗憾的是,测试时发现点击取消时仅是关闭了等待窗体,但并没有关闭长时间操作的代码,即 _method委托关联的方法还在后台运行,这好像有点不妥,但异步委托只有调用方法和侦测方法是否运行结束,并没有提供中途中止代码运行的办法,该如何处理呢? 有关委托的相关知识请参阅: 1、初识委托——System.Delegate 类 2、官方帮助《使用异步方式调用同步方法》 3、官方帮助《委托 (Visual Basic)》 本文参加了以下博文: 1、Winform等待窗口的实现(附源代码) 2、Tzhtec.Controls组件库(三)TzhtecWaitBar
相关资源可以到下载频道下载:https://download.csdn.net/user/zyjq52uys/uploads
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/zyjq52uys/article/details/89242921