讨论下在GUI里,循环执行某些代码时,无法暂停关闭的解决方案[已解决]
本帖最后由 xwt620 于 2011-6-30 21:47 编辑曾今写过一些自动安装的GUI,里面有一个【开始安装】按钮,在执行自动安装时,如果判断某个窗口TITLE未出现时,或长时间不出现,这时想点击GUI里面的暂停按钮,或者关闭按钮都是无效的,当时的解决方案是设定一个超时时间返回@error,来强行停止软件,或者设置一个HOTKEY关闭软件来解决。
如今写了一些程序在执行FOR语句或者是WHILE,do...until等循环语句时,只要没有执行完,点击GUI里面的按钮还有关闭都是没有反映的,或者说是无效
所以提出这个问题希望大家能一起讨论下算法,怎样才能实现点击GUI里面按钮能让程序暂停或关闭。
补充一下
我在论坛也搜索过相关帖子,但那些都是操作时间或者数字相关的“开始”“暂停”,而对于filecopy()等函数如果文件太大,一时间又没有完成函数,那么这时点击按钮是没有效果的,还有写自动安装也一样,如果WinWaitActive一直等不到窗口出现,那么程序就一直处于假死状态,点击GUI里的按钮是没反应的。 楼主在提问之前怎么不搜索下论坛,此类问题,论坛已经有N多相关帖子了...
事件模式可以很好的解决这类问题....
While#include <ButtonConstants.au3>
#include <GUIConstantsEx.au3>
#include <StaticConstants.au3>
#include <WindowsConstants.au3>
Opt("GUIOnEventMode", 1)
#Region ### START Koda GUI section ### Form=
$Form1 = GUICreate("Form1", 236, 254, 519, 138)
GUISetOnEvent($GUI_EVENT_CLOSE, "Quit")
$Label1 = GUICtrlCreateLabel("0", 112, 72, 10, 17)
$Button1 = GUICtrlCreateButton("开始", 80, 136, 75, 25)
GUICtrlSetOnEvent($Button1, "stat")
GUISetState(@SW_SHOW)
#EndRegion ### END Koda GUI section ###
Global $i=0,$stat = False
While 1
If $stat = True Then
$i+=1
GUICtrlSetData ($Label1,$i)
EndIf
Sleep(100)
WEnd
Func stat()
If $stat = True Then
$stat = False
GUICtrlSetData ($Button1,"开始")
Else
$stat = True
GUICtrlSetData ($Button1,"暂停")
Endif
EndFunc
Func Quit()
Exit
EndFunc
While内带For#include <ButtonConstants.au3>
#include <GUIConstantsEx.au3>
#include <StaticConstants.au3>
#include <WindowsConstants.au3>
Opt("GUIOnEventMode", 1)
#Region ### START Koda GUI section ### Form=
$Form1 = GUICreate("Form1", 236, 254, 519, 138)
GUISetOnEvent($GUI_EVENT_CLOSE, "Quit")
$Label1 = GUICtrlCreateLabel("0", 112, 72, 10, 17)
$Button1 = GUICtrlCreateButton("开始", 80, 136, 75, 25)
GUICtrlSetOnEvent($Button1, "stat")
GUISetState(@SW_SHOW)
#EndRegion ### END Koda GUI section ###
Global $stat = False
While 1
For $i=1 To 10000
If $stat = True Then
GUICtrlSetData ($Label1,$i)
EndIf
Sleep(100)
Next
WEnd
Func stat()
If $stat = True Then
$stat = False
GUICtrlSetData ($Button1,"开始")
Else
$stat = True
GUICtrlSetData ($Button1,"暂停")
Endif
EndFunc
Func Quit()
Exit
EndFunc
这个问题已经讨论了很久了。 2楼的回复确实很有参考价值,如果对于对象操作,也能如此有效那就更好了。有时有些对象的操作,失效。 可能是我的问题没有描述清楚,我在论坛也搜索过相关帖子,但是那些都是操作时间或者数字相关的“开始”“暂停”,而对于例如filecopy()等函数如果文件太大,一时间又没有完成函数,那么这时点击按钮是没有效果的,就如我以前写的自动安装一样,如果WinWaitActive一直等不到窗口出现,那么程序就一直处于假死状态。 贴出源码来看看!你这样子有谁愿意来解答! 回复 6# hzxymkb
可以参考我之前提出问题的帖子http://www.autoitx.com/thread-11175-1-1.html这个就是安装出错后,程序一直停留在WinWaitActive上,此时点击gui上按钮时,程序是没有任何反应的。
还有一个问题是我写的批量文件复制出现的问题,就是有些文件太大了,在复制过程中想点击“取消”按钮也不能取消,这个程序里用的就是filecopy()。
其实这两个问题是相似的,我理解的就是filecopy()WinWaitActive()占用了程序的线程,而不能回应其他按钮事件。
所以就需要一种方案能够解决这种问题。 #include <ButtonConstants.au3>
#include <ComboConstants.au3>
#include <EditConstants.au3>
#include <GUIConstantsEx.au3>
#include <StaticConstants.au3>
#include <WindowsConstants.au3>
$i = 0
Opt("GUIOnEventMode", 1)
$Form1_1 = GUICreate("文件复制器", 292, 150, @DesktopWidth / 3, @DesktopHeight / 3)
GUISetOnEvent($GUI_EVENT_CLOSE, "_Exit")
$Label1 = GUICtrlCreateLabel("文件类型 :", 8, 8, 58, 17)
$Combo1 = GUICtrlCreateCombo("所有类型", 72, 8, 73, 25)
$Button1 = GUICtrlCreateButton("设置", 160, 8, 51, 25, $WS_GROUP)
GUICtrlSetOnEvent(-1, "add_style")
$Label2 = GUICtrlCreateLabel("文件路径 :", 8, 40, 58, 17)
$Input2 = GUICtrlCreateInput("文件路径", 72, 40, 153, 21)
$Button2 = GUICtrlCreateButton("浏览", 232, 40, 51, 25, $WS_GROUP)
GUICtrlSetOnEvent(-1, "on_event")
$Label3 = GUICtrlCreateLabel("保存路径 :", 8, 72, 58, 17)
$Input3 = GUICtrlCreateInput("保存路径", 72, 72, 153, 21)
$Button3 = GUICtrlCreateButton("浏览", 232, 72, 51, 25, $WS_GROUP)
GUICtrlSetOnEvent(-1, "on_event")
$Label4 = GUICtrlCreateLabel("文件名称 :", 8, 104, 58, 17)
$Input4 = GUICtrlCreateInput("文件名", 72, 104, 153, 21)
$Button5 = GUICtrlCreateButton("复制", 232, 104, 51, 25, $WS_GROUP)
GUICtrlSetOnEvent(-1, "on_event")
GUISetState(@SW_SHOW)
start()
While 1
Sleep(1000)
WEnd
Func add_style()
MsgBox(0, '消息', '抱歉,暂无此功能!')
EndFunc ;==>add_style
Func on_event()
Switch @GUI_CtrlId
Case $Button2
$f_sytle = GUICtrlRead($Combo1)
$f_folder = GUICtrlRead($Input2)
If $f_sytle = "所有类型" Then $f_sytle = ".*"
If $f_sytle <> "" And StringLeft($f_sytle, 1) = "." Then
$SF2 = FileSelectFolder("选择文件夹", "", 4 + 2, $f_folder)
If $SF2 <> "" Then
If StringRight($SF2, 1) <> "\" Then $SF2 = $SF2 & "\" ;读取最右边的字符然后加 “\”
GUICtrlSetData($Input2, $SF2, "")
$search = FileFindFirstFile($SF2 & '*' & $f_sytle)
If $search = -1 Then
MsgBox(0, "错误", "文件夹中没有后缀为" & $f_sytle & "文件", 5)
GUICtrlSetData($Input2, "文件路径", "")
EndIf
EndIf
Else
MsgBox(64, "错误", "没有选择类型或输入错误", 5)
EndIf
Case $Button3
$f_folder = GUICtrlRead($Input2)
$SF3 = FileSelectFolder("选择文件夹", "", 4 + 2, $f_folder)
If $SF3 <> "我的电脑" And $SF3 <> "网上邻居" And $SF3 <> "回收站" And $SF3 <> "" Then
If StringRight($SF3, 1) <> "\" Then $SF3 = $SF3 & "\"
GUICtrlSetData($Input3, $SF3, "")
EndIf
Case $Button5
$f_sytle = GUICtrlRead($Combo1)
$f_folder = GUICtrlRead($Input2)
$s_folder = GUICtrlRead($Input3)
$filename = GUICtrlRead($Input4)
If $f_folder <> "" And $f_folder <> "文件路径" And $s_folder <> "" And $s_folder <> "保存路径" Then
If $filename = "" Then
MsgBox(0, '错误', '没有指定文件名')
Else
If $f_sytle = "所有类型" Then $f_sytle = ".*"
$search = FileFindFirstFile($f_folder & "*" & $f_sytle)
If $search <> -1 Then
While 1
$file = FileFindNextFile($search)
If @error Then ExitLoop
$files = StringInStr($file, $filename)
If $files <> 0 Then ;检查是否包含文件名的文件
FileCopy($f_folder & $file, $s_folder, 1)
$i += 1
EndIf
WEnd
If $i <> 0 Then
MsgBox(64, '结果', '成功复制包含文件名为 [' & $filename & '] 共 ' & $i & ' 个文件', 3)
Else
MsgBox(64, '结果', '文件夹中没有包含文件名为 [' & $filename & ']的文件', 3)
EndIf
$i = 0
EndIf
EndIf
Else
MsgBox(64, "错误", "没有选择路径", 5)
EndIf
EndSwitch
EndFunc ;==>on_event
Func start()
GUICtrlSetData($Combo1, ".jpg")
GUICtrlSetData($Combo1, ".gif")
GUICtrlSetData($Combo1, ".txt")
GUICtrlSetData($Combo1, ".mp3")
GUICtrlSetData($Combo1, ".wma")
GUICtrlSetData($Combo1, ".rm")
GUICtrlSetData($Combo1, ".bmp")
GUICtrlSetData($Combo1, ".au3")
GUICtrlSetData($Combo1, ".exe")
GUICtrlSetData($Combo1, ".ico")
EndFunc ;==>start
Func _Exit()
$iAnswer = MsgBox(4 + 256 + 32, "确认", "退出吗?")
Select
Case $iAnswer = 6 ;OK
Exit 0
Case $iAnswer = 7 ;Cancel
EndSelect
EndFunc ;==>_Exit写这个是因为公司里有些文件夹里的文件很多,用我的电脑打开会很慢,但是每个文件都有关键字存在,用这个程序复制出来就很方便了,但是复制时,点击程序中的关闭按钮就没有反应。
我另一个版本比这个写的更好的源码我放哪去了{:face (396):} 写这个是因为公司里有些文件夹里的文件很多,用我的电脑打开会很慢,但是每个文件都有关键字存在,用这个程 ...
xwt620 发表于 2011-6-25 22:44 http://www.autoitx.com/images/common/back.gif
天,不会吧,你这样搞,效率太低了
你需要的一个文件管理器软件,如TotalCommander,Dopus之类的。 天,不会吧,你这样搞,效率太低了
你需要的一个文件管理器软件,如TotalCommander,Dopus之类的 ...
happytc 发表于 2011-6-25 22:48 http://www.autoitx.com/images/common/back.gif
我那里没有外网,有时候就需要自己写些简单而且实用的小程序来方便自己。
而且重在学习,我提出这个问题,也是想让自己能掌握更多编程方法。 回复 10# xwt620
我说的是用软件,跟有没有外网有啥关系呀?
当然,若仅仅是练手写code就另说。 回复 11# happytc
呵呵, 我现在不仅仅是练手,也是想解决程序中的BUG,对于我提出的问题,刚刚有个搞开发的师傅跟我说,要我用多线程来解决,他的解释是我所用的函数将我的主线程的资源全部占用了,如果这个函数没有结束,此时就会出现我所说的情况,需要用主线程对副线程进行控制,这样就可以解决我的问题。
今天算是又学了一招,但是还需要花点时间去研究下多线程。 回复 12# xwt620
前面不是有人已经跟你说了,若用au3的话,别用消息模式,用事件模式就可以解决了。au3不支持多线程 回复 13# happytc
我的程序都是用的事件模式啊,而且我也很喜欢使用事件模式。 回复xwt620
au3不支持多线程happytc 发表于 2011-6-25 23:44 http://www.autoitx.com/images/common/back.gif
搜索了下,好像支持还是可以支持,只是目前没有直接可用的多线程函数,而是需要用其他DLLCALL之类的函数调用吧,只是感觉很有点麻烦,至少对于我(新手)来说---就是不会用。
页:
[1]
2