【VB开源代码栏目提醒】:以下是网学会员为您推荐的VB开源代码-vb开启程序以后程序界面会“没反应” - 其它资料,希望本篇文章对您学习有所帮助。
Vb 开启程序以后程序界面会“没反应”在
VB 编程的时候,很多人肯定碰到过开启程序以后程序界面会“没反应”,“没有响应”,但是我们
代码要求执行的任务还在正常的进行,任务执行完毕,程序界面又恢复正常,尤其是使用循环的时候很容易出现程序没响应的现象,这类问题怎么解决呢?用 DoEvnts 就可以解决。
举例:Private Sub DelayTimenum As LongDim star ends As Longstar timeGetTimeends starDo While ends - star numends timeGetTimeDoEvntsLoopEnd SubDoEvnts 是: 转让控制权,以便让操作系统处理其它的事件。
最简单的理解,比如你要在某个耗时很多的过程中(最常见的是循环),还要响应某个操作-比如控制进度条的显示,那就需要加入 DoEvnts但是,当看到这句话时,脑子里面的概念很模糊,只有一个浅薄的认识。
打个比方:如果现在有一个从 1 到 100000000 的循环,有一点编程常识的人肯定知道在这个耗时较长的循环过程中,基本上是不能进行别的操作(当然不排除一些特别的情况),但是因为某些特别的要求,你要在循环过程中,进行其他操作,这时 DoEvnts 就派上用场了。
现在,大家应该明白了 DoEvnts 的主要功能了吧。
下面举一些实例(基本上都是转载的),当然建议自己能亲自去试验,理解会深一些。
注: 后面的
代码表示如果在该处用了这个语句 以下
代码中用到了一些 api函数请用
vb 附带的 api 浏览器查阅 (转载)一. 基本用法:1.窗体启动时如果要处理的事务太多或者用 sleep 函数暂停造成其很久都不能出现时怎么办例如
代码:Private Sub Form_LoadShowDoEvntsSleep 5000End Sub通常容易想到在 sleep 前加个 show但还是不能达到预想的效果窗体虽然出来了但好象只达到了一半如果加上第 3 句将看到效果大不相同2.如果有个很耗时的循环导致程序不响应怎么办例如:Dim L As LongFor L 1 To 1000000 DoEvntsNext L如果无在循环过程中程序无法处理事件对于用户来说是不响应无法控制的3.想在循环中看到处理过程同样:Dim L As LongFor L 1 To 10000 DoEvntsText1.TextCstrlNext L无 时将无法看到 text1 中的变化而只在循环结束时看到最后结果4.怎样中止循环如果有:Private Sub Command3_ClickDim L As LongDoL L 1Debug.Print LDoEvntsLoopEnd Sub会发现当关闭窗口后debug 中的数据仍然在变化说明并没结束需要如下:Dim IsExit As BooleanPrivate Sub Command1_ClickDim L As LongIsExit FalseDo While DoEvntsIf IsExit True Then Exit DoL L 1LoopEnd SubPrivate Sub Command2_Click或者在 form_unload 模块中等等IsExit TrueEnd Sub其中 isexit 是全局变量 有些人喜欢用 end 语句来结束程序小程序固然可以但当太大或者调用了某些特殊的 api 函数后可能导致预想不到的错误如果装载了许多东西在程序结束时不处理将卸载很慢而且这种做法也极不符合正规软件的要求...总之 end 语句毛病很多此不详谈建议少使用甚至不使用二. 其基本用法大概就这些现在解析其中的一些难点1.为什么还是不能结束
代码如下:Dim IsExit As BooleanPrivate Sub Command1_ClickDim L As LongIsExit FalseDoIf IsExit True Then Exit Do 句 0DoEvnts 句 1Text1.Text CStrL 句 2L L 1LoopEnd SubPrivate Sub Form_LoadStatic N As LongN N 1MsgBox NEnd SubPrivate Sub Form_UnloadCancel As IntegerIsExit TrueEnd Sub运行结果:启动时 msg 显示 1点击 command1text1 在变化此时再点 form 右上角的小差关闭窗体发现
vb 运行控制上的按扭并没变化说明程序还在运行.如果编译成程序后运行按下 ctrldelalt 也可发现它还没结束.通过读
代码并没发现错误,怎么回事关键在于 句 2 访问了控件的属性代 码 运 行 路 径 : 当 在 doEvnts 时 程 序 释 放 控 制 权 可 以 接 收 事 件 消息form-unload 事件只能从此处产生假设此时关闭 form unload 事件发生即doEvnts 后就运行 unload
代码得到 isexitt并且 form 卸载
代码返回到doEvnts 之后运行 句 2.注意现在 form 已经卸载了text1 从哪里来呢于是 form 重新装载
代码跳到 form_load 模块运行所以在关闭窗体后可以看到msg 显示 2此模块运行完后再继续句 2 后面的
代码当下次循环遇到 句 0 时退出循环另:既然退出了循环怎么还不能结束
vb 程序规定其实其他的 windows 语言一样:窗体卸载时并不是立即卸载其模块
代码而只先卸载窗体中的控件和一些属性值程序中最后一个窗体卸载时才完全卸载.在这个单窗体程序中form 卸载时因为循环的控制无法卸载
代码失去了卸载
代码的机会导致再也不能卸载因为没卸载
代码所以运行的 句 2 是并不会出错另:既然再次运行了 form_load
代码怎么看不见窗体因为程序启动时窗体的到显示的消息而只运行此模块并没有如果在 msgbox n语句前加上 show就可以看到它了如何解决通过以上分析应该很简单把句 1 和句 2 调换一下就可以了关键:2.用了 doEvnts 速度太慢了怎么办doEvnts 的代价是速度变慢但要程序响应又不得不用其实 doEvnts 语句允许任何应用程序执行相关事件,而不仅仅是你自己的程序所以变得很慢.可以让它响应本程序事件动作需要用到 api 函数 GetInputState例如用: If GetInputState Then DoEvnts 来代替 doEvnts 可使循环运行更快3.既要同时响应事件又要控件不变化怎么办例如在一个长的循环中向 listview 控件中添加记录无 doEvnts 时程序无响应但有它时控件又闪的厉害解决办法:a.不一定每次循环都 doEvnts可以在适当时间时才用至少没那么闪b. 应用 api 函数 ValidateRect 功能是使指定的矩型区域生效通知 Windows不对指定的区域进行重画另:InvalidateRect 功能相反同时需要用到函数GetClientRect 取得指定对象的矩形区域应用rect 函数指定 listview 的矩形区不重画即可避免闪烁但还是要注意恢复重画否则看不见了真实效果4.控时循环和变速齿轮请看下面的
代码:Option ExplicitPrivate Declare Function timeGetTime Lib winmm.dll As LongDim IsExit As BooleanPrivate Sub Command1_ClickDim L As LongDim Kt As LongIsExit FalseDoKt timeGetTimedo somethingL L 1Text1.Text LDoEvnts 句 1While timeGetTime - Kt 50 句 2While AbstimeGetTime - Kt 50 句 3While AbstimeGetTime - Kt And Not IsExit 50 句 4DoEvnts 句 5WendDoEvnts 句 6If IsExit Then Exit DoLoopEnd SubPrivate Sub Form_UnloadCancel As IntegerIsExit TrueEnd Sub其中可用的
代码除去加 号的
代码就是通常的控时循环
代码运行
代码并不会出现错误但在循环过程请开启变速齿轮看看当关闭齿轮时将发现 text1.text 停止了别慌等一段时间它又会继续这要看你设定的时间这里是 50 毫秒如果设定的太长 text1.text 将半天都没变化这是怎么回事变速齿轮在启动时将 hook.dll 映射到你的程序地址运行更改了 timegettime函数获取的时间如果在句 2 和句 3 间插入 debug.print timegettimetimegettime-kt 将发现在关闭齿轮的瞬间后者变成了负值timegettime 变小了所以才造成需要等很久如果是编写游戏而用户开了齿轮那可就惨了解决方案:a.用句 3 代替句 2这个方法最简便虽然不符实但不会出问题建议使用b.不要句 5换用句 6这样就能达到效果吗 因为齿轮还是从 doEvnts 语句运行 时 才 能 插 的 进 来 所 以 只 要 kttimegettime 和 timegettime 之 间 没 有doEvnts 就不会出错ab.两种方法都有些小问题但无大碍有兴趣者请自己分析5.程序怎么死了这只是一些人编写时没注意到的小问题提醒一下:同样用上面的
代码如果设定的时间太短以至在
代码运行到句 2 时已经超时了句 5 将不能运行了当然
程序就死了哦以防万一加上句 1所以此时也只能用 a方案来解决齿轮的
问题了有必要用句 4 代替句 3 吗 除非你设定的时间太长人家想关闭你的程序要等上好半天
VB 的 doevents 作用Doevents 函数是一个很好用的函数,但很多人对它的用法不清楚或有误解。
由于我在网上查到一篇关于此函数的用法,并添加了一些内容,不敢独享,特此献出。
其中有一个“控时循环和变速齿轮”的内容,有点意思,感兴趣的可看一看。
DoEvents 函数的功能是:转让控制权,以便让操作
系统处理其它的事件。
问:为什么要用 doevents A.在需要用某一循环处理相当耗时或者很快速的
代码时就需要用到它以便用户能在起处理过程中能做其他事情即程序能被控制而不是无响应状态 B.
vb6.0 中多线程
vb 代码极度不稳定而且无法调试所以
vb 中的多线程用的很少注:是指
vb 的
代码在多线程中运行时不稳定 C.timer 控件可以起到后台运行作用但其是通过事件控制一是不稳定二是速度太慢如果想用其处理高速又耗系统的
代码更本不能达到预期的效果 下面将其某些用法和难点简介如下: 注: 1. 后面的
代码表示如果在该处用了这个语句。
2.例子中会用到 API 函数。
3.以下例子都经
vb6.0 测试成功) 一. 基本用法: 1.窗体启动时如果要处理的事务太多或者用 sleep 函数暂停造成其很久都不能出现时怎么办 例如
代码: Public Declare Sub Sleep Lib kernel32 ByVal dwMilliseconds As Long此句写入模块 Private Sub Form_Load Show DoEvents 句 3 Sleep 5000 End Sub 通常容易想到在 sleep 前加个 show但还是不能达到预想的效果窗体虽然出来了但好象只达到了一半如果加上第 3 句将看到效果大不相同 。
2.如果有个很耗时的循环导致程序不响应怎么办 例如: Dim L As Long For L 1 To 1000000 DoEvents Next L 如果无在循环过程中程序无法处理事件对于用户来说是不响应无法控制的 3.想在循环中看到处理过程 同样: Dim L As Long For L 1 To 10000 DoEvents Text1.TextCstrl Next L 无 时将无法看到 text1 中的变化而只在循环结束时看到最后结果 4.怎样中止循环 如果有: Private Sub Command1_Click Dim L As Long Do LL1 Debug.Print L 在立即窗口中显示 DoEvents Loop End Sub 会发现当关闭窗口后debug 中的数据仍然在变化说明并没结束 需要如下: Dim IsExit As Boolean Private Sub Command1_Click Dim L As Long IsExit False Do While DoEvents If IsExit True Then Exit Do LL1 Loop End Sub Private Sub Command2_Click或者在 form_unload 模块中等等 IsExit True End Sub 其中 isexit 是全局变量 有些人喜欢用 end 语句来结束程序小程序固然可以但当太大或者调用了某些特殊的 api 函数后可能导致预想不到的错误如果装载了许多东西在程序结束时不处理将卸载很慢而且这种做法也极不符合正规
软件的要求...总之 end 语句毛病很多此不详谈建议少使用甚至不使用 二. 其基本用法大概就这些现在解析其中的一些难点 1.为什么还是不能结束
代码如下: Dim IsExit As Boolean Private Sub Command1_Click Dim L As Long IsExit False Do If IsExit True Then Exit Do 句 0 DoEvents 句 1 Text1.Text CStrL 句 2 LL1 Loop End Sub Private Sub Form_Load Static N As Long NN1 MsgBox N End Sub Private Sub Form_UnloadCancel As Integer IsExit True End Sub 运行结果:启动时 msg 显示 1点击 command1text1 在变化,此时再点 form 右上角的小差关闭窗体发现
vb 运行控制上的按扭并没变化说明程序还在运行.如果编译成程序后运行按下 ctrldelalt 也可发现它还没结束. 通过读
代码并没发现错误,怎么回事 关键在于句 2访问了控件的属性 :
代码运行路径:当在 doevents 时程序释放控制权可以接收事件消息form-unload事件只能从此处产生假设此时关闭 form unload 事件发生即 doevents 后就运行 unload
代码得到 isexitt并且 form 卸载
代码返回到 doevents 之后运行句 2.注意现在 form 已经卸载了text1 从哪里来呢 于是 form 重新装载
代码跳到 form_load 模块运行所以在关闭窗体后可以看到 msg 显示 2此模块运行完后再继续句 2 后面的
代码当下次循环遇到 句 0 时退出循环 另:既然退出了循环怎么还不能结束
vb 程序规定其实其他的 windows 语言一样:窗体卸载时并不是立即卸载其模块
代码而只先卸载窗体中的控件和一些属性值程序中最后一个窗体卸载时才完全卸载. 在这个单窗体程序中form 卸载时因为循环的控制无法卸载
代码失去了卸载
代码的机会导致再也不能卸载因为没卸载
代码所以运行的句 2 是并不会出错。
另:既然再次运行了 form_load
代码怎么看不见窗体 因为程序启动时窗体的到显示的消息而只运行此模块并没有如果在 msgbox n 语句前加上 show就可以看到它了 如何解决 通过以上分析应该很简单把句 1 和句 2 调换一下就可以了关键: 2.用了 doevents 速度太慢了怎么办 doevents 的代价是速度变慢但要程序响应又不得不用,其实 doevents 语句允许任何应用程序执行相关事件,而不仅仅是你自己的程序所以变得很慢. 可以让它响应本程序事件动作需要用到 api 函数 GetInputState,它的声明语句为: Public Declare Sub Sleep Lib kernel32 ByVal dwMilliseconds As Long Public Declare Function GetInputState Lib user32 As Long 例如用: If GetInputState Then DoEvents 来代替 doevents 可使循环运行更快 3.既要同时响应事件又要控件不变化怎么办 例如在一个长的循环中向 listview 控件中添加记录无 doevents 时程序无响应但有它时控件又闪的厉害 解决办法: a.不一定每次循环都 doevents可以在适当时间时才用至少没那么闪 b.应用 api 函数 ValidateRect 功能是使指定的矩型区域生效通知 Windows 不对指定的区域进行重画 另:InvalidateRect 功能相反同时需要用到函数 GetClientRect 取得指定对象的矩形区域 应用rect 函数指定 listview 的矩形区不重画即可避免闪烁但还是要注意恢复重画否则看不见了真实效果 4.控时循环和变速齿轮 请看下面的
代码: Option Explicit Private Declare Function timeGetTime Lib winmm.dll As Long Dim IsExit As Boolean Private Sub Command1_Click Dim L As Long Dim Kt As Long IsExit False Do Kt timeGetTime do something LL1 Text1.Text L DoEvents 句 1 While timeGetTime - Kt 50 句 2 While AbstimeGetTime - Kt 50 句 3 While AbstimeGetTime - Kt And Not IsExit 50 句 4 DoEvents 句 5 Wend DoEvents 句 6 If IsExit Then Exit Do Loop End Sub Private Sub Form_UnloadCancel As Integer IsExit True End Sub 其中可用的
代码除去加 号的
代码就是通常的控时循环
代码 运行
代码并不会出现错误但在循环过程请开启变速齿轮看看 当关闭齿轮时将发现 text1.text 停止了别慌等一段时间它又会继续这要看你设定的时间这里是 50 毫秒如果设定的太长 text1.text 将半天都没变化这是怎么回事 变速齿轮在启动时将 hook.dll 映射到你的程序地址运行更改了 timegettime函数获取的时间 如果在句 2 和句 3 间插入 debug.print timegettimetimegettime-kt 将发现在关闭齿轮的瞬间后者变成了负值timegettime 变小了所以才造成需要等很久 如果是编写游戏而用户开了齿轮那可就惨了 解决
方案: a.用句 3 代替句 2这个方法最简便虽然不符实但不会出问题建议使用 b.不要句 5换用句 6这样就能达到效果吗 因为齿轮还是从 doevents 语句运行时才能插的进来所以只要 kttimegettime 和 timegettime 之间没有 doevents 就不会出错 ab.两种方法都有些小问题但无大碍有兴趣者请自己分析 5.程序怎么死了 这只是一些人编写时没注意到的小问题提醒一下: 同样用上面的
代码如果设定的时间太短以至在
代码运行到句 2 时已经超时了句 5 将不能运行了当然程序就死了哦以防万一加上句 1所以此时也只能用 a 方案来解决齿轮的问题了 有必要用句 4 代替句 3 吗 除非你设定的时间太长人家想关闭你的程序要等上好半天。
在 MSND 上的内容:在使用全局数据时避免 DoEvents 当一个函数已通过 DoEvents 放弃控制时,可相当安全地再次调用函数。
例如,下一过程将检测质数并用 DoEvents 语句周期地启动其它应用程序处理事件: Function PrimeStatus TestVal As Long As Integer Dim Lim As Integer PrimeStatus True Lim SqrTestVal For I 2 To Lim If TestVal Mod I 0 Then PrimeStatus False Exit For End If If I Mod 200 0 Then DoEvents Next I End Function 该
代码中每重复 200 次就调用一次 DoEvents 语句。
这样一来,当该环境的其余部分对事件作出响应时,只要有必要,PrimeStatus 过程就可继续计算。
考虑在调用 DoEvents 期间发生的事情。
在其它窗体和应用程序处理事件时将暂停执行应用程序
代码。
这些事件之一有可能是一个按钮单击操作,它将再次启动 PrimeStatus 过程。
这将导致重新进入 PrimeStatus 过程的,但是,因为在函数每次出现时,堆栈都为其参数和局部变量分配了空间,所以重入不会引发冲突。
当然,如果过多调用 PrimeStatus,则可能出现“溢出堆栈空间”错误。
如果 PrimeStatus 使用或改变模块级变量或全局数据,情况就会完全不同。
此时,在DoEvents 能够返回之前执行 PrimeStatus 的另一个实例,这将导致模块数据或全局数据的值完全不同于它们在调用 DoEvents之前的值。
于是,PrimeStatus 的结果将会难以预料。