狐表实现"加载中"效果的遮罩层/等待窗口方案,2行代码简单控制,支持圆角、无锯齿、透明窗体、自定义Logo、无内存泄露,样式简约现代,代码一抄即用,长时间执行的代码强烈推荐配合使用

发表日期: 2022-11-29

1.简介

1.1效果图

长时间执行的代码,加个等待窗口,让用户等待,增加友好度,一般这在web领域叫遮罩层。不过狐表Exe的UI框架里并没有集成这个,只能自己变通实现试下。

image.png

这个Loading不是挺优雅的吗?

loading.gif

1.2遮罩层特色

  1. 1代码简单,控制开关也简单。

  2. 支持圆角和透明窗体效果。

  3. 可以自定义加载中的gif动画,添加你的自己的logo,(需要你有PS功底)。

  4. 提供通用简约的GIF图,能用于任何项目场合,不搞怪异化。

  5. 弹出位置在屏幕中间+向上偏移150像素,这就不会挡住业务代码出错时的MessageBox窗口
  6. 无内存泄露【重要】。试过连续打开关闭500次,内存在10M内波动,不会无限增加,程序不崩。

image.png

 1.3前人帖子

http://www.foxtable.com/bbs/dispbbs.asp?BoardID=2&ID=152101&replyID=&skin=1

http://www.foxtable.com/bbs/dispbbs.asp?BoardID=2&ID=73365&replyID=&skin=1

http://www.foxtable.com/bbs/dispbbs.asp?BoardID=2&ID=174427&replyID=&skin=1

我选了第三个帖子去二次改造,感觉这个代码最少,好理解维护。不过它的方法存在一个严重缺陷

内存泄露严重,开循环200次打开直接程序崩了

image.png

image.png

其他是小问题:

2.教程

2.1放好图片素材

图片素材放到Images文件夹里,与待会全局代码的路径相匹配

image.png

2.2添加全局代码

image.png

'通过WaitShow()和WaitClose()来打开和关闭遮罩层,'默认30秒自动关闭
'如果非常耗时,建议自定义时间WaitShow(50000),表示50秒,并配合Try使用,Finally里放WaitClose()

'思路:
'1先配置好等待窗口和里面的GIF动态图
'2通过WaitShow()启动新线程,以模式窗口形式展示
'3过程中执行你的长耗时业务代码
'4最后WaitClose()释放窗口内存,线程也会被自动销毁

Private waitForm As System.Windows.Forms.Form '等待窗体
Private Delegate Sub CloseFormDelegate() '关闭等待窗口的委托事件
Private waitTimer As System.Threading.Timer '定时器
Private p As Point '设置等待窗口的弹出位置

Private Sub ShowWaitForm(Optional ByVal closeTimeMilliseconds As Integer = 30000)
    '1设置窗口
    waitForm = New System.Windows.Forms.Form '创建新对象
    waitForm.ShowInTaskbar = False '不在Windows底部菜单栏显示
    waitForm.MaximizeBox = False '关闭最大化按钮
    waitForm.MinimizeBox = False '关闭最小化按钮
    waitForm.ControlBox = False '关闭控制按钮
    waitForm.Text = "执行中,请稍后..." '窗口标题,底部菜单栏会显示
    waitForm.BackColor = Color.Green '绿色背景框
    waitForm.TransparencyKey = Color.Green '针对绿色进行透明化,配合上面的绿色使用。因此也要求GIF图片不能有纯绿色RGB(0,128,0)
    waitForm.FormBorderStyle = System.Windows.Forms.FormBorderStyle.None '窗口边框透明化
    waitForm.OPacity = 1 '不透明度
    waitForm.Width = 120 '窗口宽度
    waitForm.Height = 130 '窗口高度
    waitForm.Icon = New Icon(ProjectPath & "Images\logo.ico") '设置窗体图标
    waitForm.ShowIcon = True '显示窗体图标
    waitForm.StartPosition = System.Windows.Forms.FormStartPosition.Manual '窗口启动位置通过手动Location配置
    p.X = (ScreenWidth - waitForm.Width) / 2
    p.Y = (ScreenHeight - waitForm.Height) / 2 - 140 '弹出位置,最好在中间偏上方。这样不会挡住业务代码报错时的MessageBox窗口。
    waitForm.Location = p

    '2设置加载图片,并添加进窗口
    Dim waitFormPic As New System.Windows.Forms.PictureBox()
    waitFormPic.BorderStyle = BorderStyle.None '去掉图片控件的边框
    waitFormPic.Image = System.Drawing.Image.FromFile(ProjectPath & "Images\loading.gif") '设置加载显示的图片
    waitFormPic.Dock = System.Windows.Forms.DockStyle.Fill '把PictureBox填充满窗口
    waitFormPic.SizeMode = System.Windows.Forms.PictureBoxSizeMode.Zoom '图片采用缩放模式   
    waitForm.Controls.Add(waitFormPic)

    '4创建定时器,在 closeTimeMilliseconds 毫秒后执行关闭等待窗口的操作
    waitTimer = New System.Threading.Timer(
        Sub(state)
            If waitForm IsNot Nothing AndAlso Not waitForm.IsDisposed AndAlso waitForm.IsHandleCreated Then
                waitForm.Invoke(New CloseFormDelegate(AddressOf DoCloseJob))
            End If
        End Sub, 
        Nothing, 
        closeTimeMilliseconds, 
        System.Threading.Timeout.Infinite
    )

    '5以模式窗口显示
    waitForm.ShowDialog()
End Sub

'显示等待窗口(默认30秒关闭)
Public Sub WaitShow(Optional ByVal closeTimeMilliseconds As Integer = 30000)
    Try
        Dim upgradeThread = New System.Threading.Thread(
            Sub()
                ShowWaitForm(closeTimeMilliseconds)
            End Sub
        )
        upgradeThread.Start()
    Catch Err As System.Threading.ThreadAbortException
        MessageBox.Show(Err.Message)
    End Try
End Sub

'关闭等待窗口
Public Sub WaitClose()
     If waitTimer IsNot Nothing Then
        waitTimer.Dispose() '关闭定时器
    End If
    
    System.Threading.Thread.Sleep(150) '必须等待150ms,防止窗口没启动好就立刻触发关闭
    If waitForm IsNot Nothing AndAlso Not waitForm.IsDisposed AndAlso waitForm.IsHandleCreated Then
        waitForm.Invoke(New CloseFormDelegate(AddressOf DoCloseJob))
    End If
End Sub

'关闭窗口事件,如果窗口被强行关闭,也会触发
'遮罩层是个异步线程启动的窗口,被强行关闭也不会影响主窗口的代码执行
Private Sub DoCloseJob()
    BaseMainForm.Activate() '重要!重新激活主窗口,这样焦点才能回到本程序
    waitForm.Dispose() '关闭并释放内存,线程也会随后自动结束
End Sub

2.3使用方法

2.3.1自动关闭方法

如果你确定代码执行时间较短,且逻辑简单不容易报错

WaitShow '30秒内自动关闭   
 
'你的长时间运行代码,例如保存
DataTables("数据权限表").Save

WaitClose
2.3.1手动关闭方法

- 如果预计代码时间长,且逻辑复杂容易易出错,推荐配合Try使用,Finally里放WaitClose(),防止因为业务代码异常而导致遮罩层不关闭

- 当然如果你有把握,中间过程代码不会出错的,不用Try,直接使用也没问题。如果真的出现异常,你可以告诉客户在底部菜单栏右键强制关闭。它的关闭,并不会影响原来主线程在做的事情。

Try
    WaitShow(60000)'手动设置60秒后关闭
    '你的长时间运行代码,例如保存
    DataTables("数据权限表").Save
Catch ex As Exception 
    MessageBox.Show(ex.Message)
Finally
    WaitClose
End Try
3.自定义加载GIF动画

这个需要你有PS基础,我已经提供了我这次使用的gif图的原PSD文件。需要在PS里打开,并且启动PS的`时间轴`功能。你要去百度学习一下PS的时间轴玩法和GIF保存方法

3.1添加自定义logo和背景

例如我加一个迈宝伦科技官网的logo去中间

image.png

image.png


成品效果:

loading_带logo.gif

3.2透明背景和圆角

gif是支持透明背景的,圆角也支持,在PS做好即可。唯一要注意就是生成GIF图时,圆角要设置相应的杂边颜色,不然会有难看的白色锯齿

image.png


以下是正确保存方法

image.png

image.png

3.3注意不要用某个绿色

在刚才的全局代码里有一个

...
waitForm.BackColor = Color.Green '绿色背景框
waitForm.TransparencyKey = Color.Green '针对绿色进行透明化,配合上面的绿色使用。因此也要求GIF图片不能有纯绿色RGB(0,128,0)
...

这个是狐表窗口实现边框透明的关键,设置绿色边框,并对绿色进行透明化。所以你如果GIF里刚好包含了RGB(0,128,0)的绿色,也会被抠图走,穿孔很丑了。

如果你的Gif图一定要用这种绿色,我推荐你可以换别的颜色组合,例如Color.Red。就跟好莱坞拍戏用绿幕,演员就别穿颜色相近的绿衣服一个道理。

4.案例源码下载

链接:https://pan.baidu.com/s/1seszoyi3mO9wNr-1EvhwBA?pwd=frwy 

提取码:frwy 

版本说明:程序需要20220818或以上的商业版,或者用狐表官网最新的试用版。如果你没有这个版本也没关系,可以下载源码,只要里面的GIF素材和PS素材,配合上面分享的代码,复制就能用,不一定非得开源码看。


随便看看
商务联系QQ : 2385350359

Copyright 2016-2023 江门蓬江区华越科技公司 版权所有 | 承接软件定制开发,欢迎联系
粤ICP备19148806号-5