请教一个关于循环执行任务的问题
本帖最后由 水木子 于 2019-12-29 19:21 编辑最近在帮朋友写一个小程序,涉及到需要循环挨个执行任务,一直没有什么好的方法,特来请教下大家,还望大家不吝赐教。
我先说明下需求吧!
1、每个循环的循环次数是不定的,不一定都是10次。
2、必须等前面的循环执行完毕,再接着执行后面的循环。比如勾选了 “循环2”和“循环4”,那么就先执行完“循环2”,之后再开始“循环4”
3、可随时相应按钮控制,比如循环开始以后,可以点击“结束”按钮,立即结束循环。
不知道我表达清楚没有,目前我的解决方法如下,但是我始终觉得不够好。还请大家帮忙想想有没有其他更好的方法。
看似一个挺简单的问题,但我思索了许久,一直没有想出比较好的解决方法。
Global $bBoolean = True, $iZ
Global $Checkbox
Global $hGUI = GUICreate('', 300, 400)
$Checkbox = GUICtrlCreateCheckbox('循环1', 60, 50, 97, 17)
GUICtrlSetFont(-1, 12, 400, 0, '微软雅黑')
$Checkbox = GUICtrlCreateCheckbox('循环2', 180, 50, 97, 17)
GUICtrlSetFont(-1, 12, 400, 0, '微软雅黑')
$Checkbox = GUICtrlCreateCheckbox('循环3', 60, 100, 97, 17)
GUICtrlSetFont(-1, 12, 400, 0, '微软雅黑')
$Checkbox = GUICtrlCreateCheckbox('循环4', 180, 100, 97, 17)
GUICtrlSetFont(-1, 12, 400, 0, '微软雅黑')
$Label1 = GUICtrlCreateLabel('', 50, 200, 200, 20, 0x01 + 0x0200)
GUICtrlSetFont(-1, 12, 400, 0, '微软雅黑')
$Label2 = GUICtrlCreateLabel('准备就绪', 50, 250, 200, 20, 0x01 + 0x0200)
GUICtrlSetFont(-1, 14, 400, 0, '微软雅黑')
$Button1 = GUICtrlCreateButton('开始', 50, 300, 80, 30)
$Button2 = GUICtrlCreateButton('结束', 170, 300, 80, 30)
GUISetState()
While 1
$nMsg = GUIGetMsg()
Switch $nMsg
Case -3
Exit
Case $Button1
$bBoolean = True
If GUICtrlRead($Checkbox) = 1 and $bBoolean = True Then
$bBoolean = False
$iZ = 0
GUICtrlSetData($Label1, '正在执行 循环1')
AdlibRegister('MyFunc', 500)
Wait()
EndIf
If GUICtrlRead($Checkbox) = 1 and $bBoolean = TrueThen
$bBoolean = False
$iZ = 0
GUICtrlSetData($Label1, '正在执行 循环2')
AdlibRegister('MyFunc', 500)
Wait()
EndIf
If GUICtrlRead($Checkbox) = 1 and $bBoolean = TrueThen
$bBoolean = False
$iZ = 0
GUICtrlSetData($Label1, '正在执行 循环3')
AdlibRegister('MyFunc', 500)
Wait()
EndIf
If GUICtrlRead($Checkbox) = 1 and $bBoolean = TrueThen
$bBoolean = False
$iZ = 0
GUICtrlSetData($Label1, '正在执行 循环4')
AdlibRegister('MyFunc', 500)
Wait()
EndIf
Case $Button2
AdlibUnRegister()
$bBoolean = False
GUICtrlSetData($Label1, '手动结束循环')
EndSwitch
WEnd
Func Wait()
While 1
If $bBoolean = True Then ExitLoop
$nMsg2 = GUIGetMsg()
Switch $nMsg2
Case -3
Exit
Case $Button2
AdlibUnRegister()
$bBoolean = False
GUICtrlSetData($Label1, '手动结束循环')
ExitLoop
EndSwitch
WEnd
EndFunc ;==>Wait
Func MyFunc()
$iZ += 1
GUICtrlSetData($Label2, $iZ)
If $iZ = 10 Then
AdlibUnRegister()
$bBoolean = True
GUICtrlSetData($Label1, '循环完成')
EndIf
EndFunc ;==>MyFunc
挺好的 好像木有问题啊~~ afan 发表于 2019-12-29 19:18
挺好的 好像木有问题啊~~
谢谢前辈的支持,请不要受我代码的影响,如果让你来写,这样的问题,你会用什么方法呢?
本帖最后由 afan 于 2019-12-29 19:51 编辑
不知道木子的用途,我只能按自己的方式搞一下
Opt('GUIOnEventMode', 1)
Global $hGUI, $Checkbox, $Label1, $Label2, $Button2
_Test()
Func _Test()
$hGUI = GUICreate('', 300, 400)
GUISetFont(12, 400, 0, '微软雅黑')
GUISetOnEvent(-3, '_Close')
$Checkbox = GUICtrlCreateCheckbox('循环1', 60, 50, 97, 17)
$Checkbox = GUICtrlCreateCheckbox('循环2', 180, 50, 97, 17)
$Checkbox = GUICtrlCreateCheckbox('循环3', 60, 100, 97, 17)
$Checkbox = GUICtrlCreateCheckbox('循环4', 180, 100, 97, 17)
$Label1 = GUICtrlCreateLabel('', 50, 200, 200, 20, 0x01 + 0x0200)
$Label2 = GUICtrlCreateLabel('准备就绪', 50, 250, 200, 20, 0x01 + 0x0200)
GUICtrlCreateButton('开始', 50, 300, 80, 30)
GUICtrlSetOnEvent(-1, '_Start')
$Button2 = GUICtrlCreateButton('结束', 170, 300, 80, 30)
GUISetState()
While 1
Sleep(1000)
WEnd
EndFunc ;==>_Test
Func _Start()
Opt('GUIOnEventMode', 0)
For $ii = 0 To 3
If GUICtrlRead($Checkbox[$ii]) = 1 Then
GUICtrlSetData($Label1, '正在执行 循环' & $ii + 1)
For $jj = 1 To 10
$ts = TimerInit()
Do
Switch GUIGetMsg()
Case -3
_Close()
Case $Button2
GUICtrlSetData($Label1, '手动结束循环')
ExitLoop 3
EndSwitch
Until TimerDiff($ts) > 500
GUICtrlSetData($Label2, $jj)
Next
GUICtrlSetData($Label1, '循环完成')
EndIf
Next
Opt('GUIOnEventMode', 1)
EndFunc ;==>_Start
Func _Close()
Exit
EndFunc ;==>_Close 本帖最后由 水木子 于 2019-12-29 19:58 编辑
afan 发表于 2019-12-29 19:48
不知道木子的用途,我只能按自己的方式搞一下
Opt('GUIOnEventMode', 1)
是这样的,这个小程序的主要作用是,定时监测某窗口上是否出现某按钮,如果出现了则按下,$iZ += 1
如此往复 当 $iZ =n则结束循环,继续执行下一个循环。中途可以手动停止监测。就是这么回事。
另外前辈给出的代码,我这边执行出错。Until TimerDiff($ts) $ts未申明。
本帖最后由 zghwelcome 于 2019-12-29 20:05 编辑
#include <WindowsConstants.au3>
Global $bBoolean = True
Global $Checkbox
Global $hGUI = GUICreate('', 300, 400)
$Checkbox = GUICtrlCreateCheckbox('循环1', 60, 50, 97, 17)
GUICtrlSetFont(-1, 12, 400, 0, '微软雅黑')
$Checkbox = GUICtrlCreateCheckbox('循环2', 180, 50, 97, 17)
GUICtrlSetFont(-1, 12, 400, 0, '微软雅黑')
$Checkbox = GUICtrlCreateCheckbox('循环3', 60, 100, 97, 17)
GUICtrlSetFont(-1, 12, 400, 0, '微软雅黑')
$Checkbox = GUICtrlCreateCheckbox('循环4', 180, 100, 97, 17)
GUICtrlSetFont(-1, 12, 400, 0, '微软雅黑')
$Label1 = GUICtrlCreateLabel('', 50, 200, 200, 20, 0x01 + 0x0200)
GUICtrlSetFont(-1, 12, 400, 0, '微软雅黑')
$Label2 = GUICtrlCreateLabel('准备就绪', 50, 250, 200, 20, 0x01 + 0x0200)
GUICtrlSetFont(-1, 14, 400, 0, '微软雅黑')
$Button1 = GUICtrlCreateButton('开始', 50, 300, 80, 30)
$Button2 = GUICtrlCreateButton('结束', 170, 300, 80, 30)
GUISetState()
GUIRegisterMsg($WM_SYSCOMMAND, "On_WM_SYSCOMMAND")
GUIRegisterMsg($WM_COMMAND, "WM_COMMAND")
While 1
$nMsg = GUIGetMsg()
Switch $nMsg
Case -3
Exit
Case $Button1
$bBoolean = True
For $i = 0 To UBound($Checkbox) - 1
If Not $bBoolean Then ExitLoop
If GUICtrlRead($Checkbox[$i]) = 1 Then
Local $vLoopNum = Random(5,10,1)
GUICtrlSetData($Label1, '正在执行 循环' & $i + 1)
_Loop($i + 1 ,$vLoopNum)
EndIf
Next
EndSwitch
WEnd
Func _Loop($vLoopIndex , $vLoopNum)
For $j = 1 To $vLoopNum
GUICtrlSetData($Label2, '循环' & $vLoopIndex & ' ' & $j & '/' & $vLoopNum)
For $t = 1 To 2
Sleep(250)
If Not $bBoolean Then Return GUICtrlSetData($Label1, '手动结束循环')
Next
Next
EndFunc ;==>_Loop
Func WM_COMMAND($hWnd, $iMsg, $iwParam, $ilParam)
$iCode = BitShift($iwParam, 16)
Switch $ilParam
Case GUICtrlGetHandle($Button2)
$bBoolean = False
EndSwitch
Return
EndFunc ;==>WM_COMMAND
Func On_WM_SYSCOMMAND($hWnd, $nMsg, $wParam, $lParam)
Local Const $SC_CLOSE = 0xF060
Switch BitAND($wParam, 0xFFF0)
Case $SC_CLOSE
GUIDelete()
Exit
EndSwitch
Return 'GUI_RUNDEFMSG'
EndFunc ;==>On_WM_SYSCOMMAND
最好的方式应该是hook检测窗口的消息
水木子 发表于 2019-12-29 19:57
是这样的,这个小程序的主要作用是,定时监测某窗口上是否出现某按钮,如果出现了则按下,$iZ += 1
如此 ...
之前编辑帖子给误删了,后来加上了
高亮的TAB间距太大了,难看 本帖最后由 水木子 于 2019-12-29 20:09 编辑
zghwelcome 发表于 2019-12-29 20:03
最好的方式应该是hook检测窗口的消息
嗯!这个方法我有想过,但是没有成功。故出此下策。
谢谢!前辈的思路,感激不尽。
本帖最后由 水木子 于 2019-12-29 20:30 编辑
afan 发表于 2019-12-29 20:05
之前编辑帖子给误删了,后来加上了
高亮的TAB间距太大了,难看
前辈这个方法我之前有想过,但是我一直以为循环中有 Sleep 会影响 GUIRegisterMsg 的相应速度,所以就没有继续往下深入,经测试是可行的,看来我要对 GUIRegisterMsg 重新审视了,谢谢!
另外不得不佩服前辈写代码的速度,可以说已经达到了信手拈来的地步,我的帖子刚开,前辈立即跟上。思路与代码也随之跟上,可见神速!佩服,佩服!
水木子 发表于 2019-12-29 20:25
前辈这个方法我之前有想过,但是我一直以为循环中有 Sleep 会影响 GUIRegisterMsg 的相应速度,所以就没 ...
木子过奖了哦这不也是在你的代码和思路上改的吗各有千秋罢了~
zghwelcome 的方法也不错,只是个人偏好尽量独立函数化处理完成,尽量少与系统消息挂钩,系统消息我一般只处理主脚本的事件。当然这里只是个小脚本用不着想太多,习惯使然~ 水木子 发表于 2019-12-29 19:57
是这样的,这个小程序的主要作用是,定时监测某窗口上是否出现某按钮,如果出现了则按下,$iZ += 1
如此 ...
我也写过这样一个守护程序,其中循环时的退出,用的热键。
其他的就是循环,在循环中设置几个全局数组,当做触发时机。
页:
[1]