Ok, so I'm creating an AutoIt GUI executable to automate some functions in a website. However, I cannot find a way to break the While loop that executes the function I've created using a "STOP" button I've created. Therefore, it runs indefinitely, and I cannot quit the program. In theory, it should work, but I feel I'm missing something. Any help, folks?
#include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>
#include <IE.au3>
Global $msg, $instructions, $AutoLevel, $NumDogsBox, $NumDogs, $IE, $i, $o
$IE = _IECreateEmbedded()
GUICreate("Automatic Dog Feeder for Criminal Case", 900, 690)
$instructions = GUICtrlCreateButton(' Instructions ', 725, 5)
GUICtrlCreateLabel("# of Dogs: ",740,40)
$NumDogsBox = GUICtrlCreateInput("", 815, 37, 25)
$AutoLevel = GUICtrlCreateButton(' Begin Auto Feed Dog ', 700, 65)
GUICtrlCreateObj($IE, 1, 100, 915, 610)
GUISetState(#SW_SHOW)
_IENavigate($IE, "http://apps.facebook.com/criminalcase")
$IE.Document.Body.Scroll = "no"
_IEAction($IE, "stop")
While 1
$msg = GUIGetMsg()
Select
Case $msg = $GUI_EVENT_CLOSE
ExitLoop
Case $msg = $instructions
MsgBox(0,"Instructions","1.) Log in to Facebook (if not already) in the window below" & #CRLF & "2.) Clear any notifications and get to the map screen" & #CRLF & "3.) Click on the dog bowl icon on the right of the map" & #CRLF & "4.) Enter the number of dogs you have to level up" & #CRLF & "5.) Click the Begin Auto Feed Dog button at the bottom of the window")
Case $msg = $AutoLevel
$NumDogs = GUICtrlRead($NumDogsBox)
AutoDogLevel()
EndSelect
WEnd
Func AutoDogLevel()
While 1
$stop = GUICtrlCreateButton('STOP',830,65)
$i=0
While $i < $NumDogs
If $msg = $stop Then
ExitLoop
Endif
MsgBox(0,"","1xp" & $i+1)
ControlClick("[CLASS:MacromediaFlashPlayerActiveX]","","","left",1,156,651)
Sleep(2000)
If $msg = $stop Then
ExitLoop
Endif
ControlClick("[CLASS:MacromediaFlashPlayerActiveX]","","","left",1,723,524)
MsgBox(0,"","Next Dog")
Sleep(2000)
$i = $i+1
WEnd
If $msg = $stop Then
ExitLoop
Endif
While $i > 0
If $msg = $stop Then
ExitLoop
Endif
ControlClick("[CLASS:MacromediaFlashPlayerActiveX]","","","left",1,62,525)
MsgBox(0,"","Previous Dog")
If $msg = $stop Then
ExitLoop
Endif
Sleep(1000)
$i=$i-1
WEnd
If $msg = $stop Then
ExitLoop
Endif
Sleep(3000)
WEnd
EndFunc
So, now I'm stuck. Any help will be greatly appreciated.
It's not a good idea to have more than 1 message loop for a GUI. Instead of doing it like this, I suggest keeping a variable for the current state, and only implementing a single loop. You also have some very large sleeps inside the message loop as well.
I haven't tested the code, but here is the message loop re-written to use a state variable and timers instead of multiple loops and sleeps. This is a much better design that will ensure your GUI is always responsive to ALL the buttons, and I think you'll find it easier to work with as well once you get used to the structure.
Local $iState = 0, $i, $iTimer
While 1
$msg = GUIGetMsg()
Select
Case $msg = $GUI_EVENT_CLOSE
ExitLoop
Case $msg = $instructions
MsgBox(0, "Instructions", "1.) Log in to Facebook (if not already) in the window below" & #CRLF & "2.) Clear any notifications and get to the map screen" & #CRLF & "3.) Click on the dog bowl icon on the right of the map" & #CRLF & "4.) Enter the number of dogs you have to level up" & #CRLF & "5.) Click the Begin Auto Feed Dog button at the bottom of the window")
Case $msg = $AutoLevel
$NumDogs = GUICtrlRead($NumDogsBox)
$stop = GUICtrlCreateButton('STOP', 830, 65)
$iState = 1
$i = 0
Case Else
If $iState = 1 Then
If $i >= $NumDogs Then
$iState = 3
ContinueLoop
EndIf
MsgBox(0, "", "1xp" & $i + 1)
ControlClick("[CLASS:MacromediaFlashPlayerActiveX]", "", "", "left", 1, 156, 651)
$iState = 2
$iTimer = TimerInit()
ElseIf $iState = 2 Then
If TimerDiff($iTimer) < 2000 Then ContinueLoop
ControlClick("[CLASS:MacromediaFlashPlayerActiveX]", "", "", "left", 1, 723, 524)
MsgBox(0, "", "Next Dog")
$iTimer = TimerInit()
$i = $i + 1
ElseIf $iState = 3 Then
If TimerDiff($iTimer) < 1000 Then ContinueLoop
If $i <= 0 Then
$iState = 1
ContinueLoop
EndIf
ControlClick("[CLASS:MacromediaFlashPlayerActiveX]", "", "", "left", 1, 62, 525)
MsgBox(0, "", "Previous Dog")
$iTimer = TimerInit()
$i = $i - 1
EndIf
EndSelect
WEnd
Related
I have a question I wrote this script to format an arabic text to a certain format. But I found a problem then when I type a longer sentence it adds more dots then there are letters. I will paste the code here and explain what the problem is.
import itertools
while True:
input_cloze_deletion = input("\nEnter: text pr 'exit'\n> ")
input_exit_check = input_cloze_deletion.strip().lower()
if input_exit_check == "exit":
break
# copy paste
interpunction_list = ["الله", ",", ".", ":", "?", "!", "'"]
# copy paste
interpunction_list = [ ",", ".", ":", "?", "!", "'", "-", "(", ")", "/", "الله", "اللّٰـه"]
text_replace_0 = input_cloze_deletion.replace(",", " ,")
text_replace_1 = text_replace_0.replace(".", " .")
text_replace_2 = text_replace_1.replace(":", " :")
text_replace_3 = text_replace_2.replace(";", " ;")
text_replace_4 = text_replace_3.replace("?", " ?")
text_replace_5 = text_replace_4.replace("!", " !")
text_replace_6 = text_replace_5.replace("'", " ' ")
text_replace_7 = text_replace_6.replace("-", " - ")
text_replace_8 = text_replace_7.replace("(", " ( ")
text_replace_9 = text_replace_8.replace(")", " ) ")
text_replace_10 = text_replace_9.replace("/", " / ")
text_replace_11 = text_replace_10.replace("الله", "اللّٰـه")
text_split_list = text_replace_11.split()
count_number = []
letter_count_list = []
index_list = itertools.cycle(range(1, 4))
for letter_count in text_split_list:
if letter_count in interpunction_list:
letter_count_list.append(letter_count)
elif "ـ" in letter_count:
letter_count = len(letter_count) - 1
count_number.append(letter_count)
print(letter_count)
else:
letter_count = len(letter_count)
count_number.append(letter_count)
print(letter_count)
for count in count_number:
letter_count_list.append(letter_count * ".")
zip_list = zip(text_split_list, letter_count_list)
zip_list_result = list(zip_list)
for word, count in zip_list_result:
if ((len(word)) == 2 or word == "a" or word == "و") and not word in interpunction_list :
print(f" {{{{c{(next(index_list))}::{word}::{count}}}}}", end="")
elif word and count in interpunction_list:
print(word, end = "")
else:
print(f" {{{{c{(next(index_list))}::{word}::{count}}}}}", end="")
when I type كتب عليـ ـنا و علـ ـي
the return is {{c1::كتب::...}} {{c2::عليـ::...}} {{c3::ـنا::...}} {{c1::و::..}} {{c2::علـ::..}} {{c3::ـي::..}}
but it should be
{{c1::كتب::...}} {{c2::عليـ::...}} {{c3::ـنا::..}} {{c1::و::.}} {{c2::علـ::..}} {{c3::ـي::.}}
I add a print function the print the len() results and the result is correct but it add an extra dot in some case.
But when I type just a single "و" it does a correct len() function but when I input a whole sentence it add an extra dot and I don't know why.
please help
I am a total novice with visual basic and teaching myself as I go along. I am building a VB in studio 2008 (I'm obliged to use this version) that logs into a device , transmits log in and password and then transmits commands read from a .txt file using reflections. All of this is working fine. The device executes the command and outputs 1 of 28 possible responses.
I am using select case to evaluate the responses and act accordingly. The device session stops as expected when EXECUTED is seen in the session window, my test data is designed so the first response I get is "EXECUTED", the weird thing is my VB "sees" the EXECUTED message (Case 1) but select case responds as if it has seen FAILED (Case 2), subsequent lines of the test data illicit different cases (5 and 6) but the response is always the next case along. I have tried Case n, case is = n, case "string value" but I get errors.
Here's my code - note that I haven't defined all 28 cases yet but the undefined ones are REM'ed out in my active version. Any ideas or suggestions would be gratefully received!
Option Explicit On
Public Class modCaseSelect
Shared Sub Dev_Responses(ByVal refl)
Dim Result As String
Dim CR = vbCr
Dim Resp As Integer
Dim Dev_Resp(28) As String
Dev_Resp(0) = "RUNNING"
Dev_Resp(1) = "EXECUTED"
Dev_Resp(2) = "FAILED"
Dev_Resp(3) = "SEMANTICS ERROR"
Dev_Resp(4) = "NONEXISTENT"
Dev_Resp(5) = "NOT FOUND"
Dev_Resp(6) = "SPECIAL"
Dev_Resp(7) = "CONFIRM: Y/N"
Dev_Resp(8) = "CONFIRM (Y/N)"
Dev_Resp(9) = "CONFIRM EXECUTION: Y/N"
Dev_Resp(10) = "ALREADY EXECUTED"
Dev_Resp(11) = ""
Dev_Resp(12) = ""
Dev_Resp(13) = ""
Dev_Resp(14) = ""
Dev_Resp(15) = ""
Dev_Resp(16) = ""
Dev_Resp(17) = ""
Dev_Resp(18) = ""
Dev_Resp(19) = ""
Dev_Resp(20) = ""
Dev_Resp(21) = ""
Dev_Resp(23) = ""
Dev_Resp(23) = ""
Dev_Resp(24) = ""
Dev_Resp(25) = ""
Dev_Resp(26) = ""
Dev_Resp(27) = ""
Dev_Resp(28) = "IN PROGRESS"
With refl
Select Case .WaitForStrings(Dev_Resp, "0:4:30") 'checkDev_Resp
Case 0 ' "RUNNING"
Result = Dev_Resp(0)
Resp = MsgBox((Dev_Resp(0) & CR & CR & Continue?"), 17, "Case 0 error")
Case 1 ' "EXECUTED"
Result = Dev_Resp(1)
Resp = MsgBox((Dev_Resp(1) & CR & CR & "Continue?"), 17, "Case 1")
Case 2 ' "FAILED"
Result = Dev_Resp(2)
Resp = MsgBox((Dev_Resp(2) & CR & CR & "Continue?"), 17, "Case 2 error")
Case 3 ' "SEMANTICS ERROR"
Result = Dev_Resp(3)
Resp = MsgBox((Dev_Resp(3) & CR & CR & "Continue?"), 17, "Case 3 error")
Case 4 ' "NONEXISTENT"
Result = Dev_Resp(4)
Resp = MsgBox((Dev_Resp(4) & CR & CR & "Continue?"), 17, "Case 4 error")
Case 5 ' "NOT FOUND"
Result = Dev_Resp(5)
Resp = MsgBox((Dev_Resp(5) & CR & CR & "Continue?"), 17, "Case 5 error")
Case 6 ' "SPECIAL"
Result = Dev_Resp(6)
Resp = MsgBox((Dev_Resp(6) & CR & CR & "Continue?"), 17, "Case 6 error")
Case 7 ' "CONFIRM: Y/N"
Result = Dev_Resp(7)
.Transmit("Y" & CR)
Case 8 ' "CONFIRM (Y/N)"
Result = Dev_Resp(8)
.Transmit("Y" & CR)
Case 9 ' "CONFIRM EXECUTION: Y/N"
Result = Dev_Resp(9)
.Transmit("Y" & CR)
Case 10 ' "ALREADY EXECUTED"
Result = Dev_Resp(10)
Resp = MsgBox((Dev_Resp(10) & CR & CR & "Continue?"), 17, "Case 10 error")
Case 11 ' ""
Result = Dev_Resp(11)
Case 12 ' ""
Result = Dev_Resp(12)
Case 13 ' ""
Result = Dev_Resp(13)
Case 14 ' ""
Result = Dev_Resp(14)
Case 15 ' ""
Result = Dev_Resp(15)
Case 16 ' ""
Result = Dev_Resp(16)
Case 17 ' ""
Result = Dev_Resp(17)
Case 18 ' ""
Result = Dev_Resp(18)
Case 19 ' ""
Result = Dev_Resp(19)
Case 20 ' ""
Result = Dev_Resp(20)
Case 21 ' ""
Result = Dev_Resp(21)
Case 22 ' ""
Result = Dev_Resp(22)
Case 23 ' ""
Result = Dev_Resp(23)
Case 24 ' ""
Result = Dev_Resp(24)
Case 25 ' ""
Result = Dev_Resp(25)
Case 26 ' ""
Result = Dev_Resp(26)
Case 27 ' ""
Result = Dev_Resp(27)
Case 28 ' "IN PROGRESS"
Result = Dev_Resp(28)
Resp = MsgBox((Dev_Resp(28) & CR & CR & "Continue?"), 17, "Case 28 error")
Case Else
End Select
End With
End Sub
End Class
You are missing a double quote " in your first Case. Try changing it to this:
Case 0 ' "RUNNING"
Result = Dev_Resp(0)
Resp = MsgBox((Dev_Resp(0) & CR & CR & "Continue?"), 17, "Case 0 error")
Notice I've added the double quote before "Continue?".
Get rid of the With statement. Create and assign a holder variable and use that with the select statement. Doing so will allow you to see what is actually getting passed into the select statement by setting a stop point in the debugger.
Dim temp_resp as integer = refl.WaitForStrings(Dev_Resp, "0:4:30")
Select Case temp_resp
'the case statements here.
End Select
Reflections WaitForStrings uses a zero-based array parameter, but it returns a 1-based index of strings. Waitforstrings sees array entry zero as the first valid entry so the first select case (Case = 1) corresponds to array entry 0.
This question is related to Breaking parent loop in tcl , but I am not able to implement the answer to my current code.
I have a proc written in VBA for Excel which uses "Exit do":
Do While i < numofentries
Debug.Print "------------------"
Debug.Print "j = " & j
Debug.Print "length | Element i"
path_beg = i
path_end = i
Length = 0
length_l = 0
length_u = 0
blnAngle = True
Do While Length < minlength
If (angles(i) < limitangle Or path_beg = i) Then
Length = Length + ElemEdgeLengths(i)
Debug.Print Length & " | " & i
path_end = i
i = i + 1
If i = numofentries Then Exit Do
Else
Debug.Print "Angle change..."
If path_end = path_beg Then
path(j - 1) = path_end
blnAngle = False
Debug.Print "1 Elm only: included to predecessor path:"
Debug.Print "path_end of path j = " & j - 1 & " changed to " & path_end
Else
path(j) = path_end
j = j + 1
blnAngle = False
Debug.Print path_end - path_beg + 1 & " Elms: own path with length " & Length
End If
Exit Do
End If
Loop
If blnAngle = True Then
length_l = Abs(Length - ElemEdgeLengths(path_end - 1) - minlength)
length_u = Abs(Length - minlength)
If length_l <= length_u Then
i = path_end
path(j) = path_end - 1
j = j + 1
Debug.Print "last Elm set to " & path_end - 1
Else
path(j) = path_end
j = j + 1
Debug.Print "last Elm is " & path_end
End If
End If
Loop
I have "translated" the sub to tcl like this, but I am not able to simulate the behaviour of ExitDo correctly. How can I recode the VBA Sub in Tcl correctly ? :
proc magictrap {code body} {
if {$code <= 4} {error "bad magic code"}; # Lower values reserved for Tcl
if {[catch {uplevel 1 $body} msg opt] == $code} return
return -options $opt $msg
}
proc magicthrow code {return -code $code "doesn't matter what this is"}
proc pathfinder {ElemEdgeLengths minlength LimitAngle angles} {
set j 0
set i 0
set numofentries [llength $ElemEdgeLengths]
while { $i < $numofentries } {
set path_beg $i
set path_end $i
set length 0
set length_l 0
set length_u 0
set blnAngle 1
while { ( $length < $minlength ) } {
if { ( [lindex $angles $i] < $LimitAngle ) || ( $path_beg == $i ) } {
set length [ expr { $length + [lindex $ElemEdgeLengths $i] } ]
set path_end $i
incr i
if { $i == $numofentries } { magicthrow 5 }
} else {
if { $path_end == $path_beg } {
set k [expr { $j - 1 }]
set path($k) $path_end
set blnAngle 0
} else {
set path($j) $path_end
incr j
set blnAngle 0
}
set length inf
}
}
if { $blnAngle == 1 } {
set length_l [ expr { abs( $length - [lindex $ElemEdgeLengths [expr {$path_end - 1} ] ] - $minlength ) } ]
set length_u [ expr { abs( $length - $minlength ) } ]
}
if { $length_l <= $length_u } {
set i $path_end
set path($j) [expr {$path_end - 1}]
incr j
} else {
set path($j) $path_end
incr j
}
}
return $path
}
"break" exits the innermost loop.
you could set a boolean variable at the "exit do" location:
set blnBreak 1
break
just outside the loop you will have to test it:
if { $blnBreak == 1 } {
break
}
The VB Exit Do corresponds very closely to break in Tcl (and many other languages besides).
I'm doing a bit of code that pulls through rows from a database connection and should return a linenumber for each row. I'm doing this in the following way.
linenum = 0
Do While (rsData.Read())
linenum = linenum + 1
Now when I ouput a DB connection with 8 rows, the linenumbers for each of the rows return as 1222222.
I need to determine the correct numbers so I can do the following to change row styles.
If ((linenum / 2) = Int(linenum / 2)) Then
html += Chr(13) & "<tr class=""openrow2"">"
Else
html += Chr(13) & "<tr class=""openrow1"">"
End If
Any ideas why my rows past the first one seem to only get referred to as linenumber 2 rather than the next number in the series?
Thanks!
Just a shoot in the dark, but where is your loop statement ?
Also if linenum is an integer why don't use the MOD operator ?
linenum = 0
Do While rsData.Read()
linenum = linenum + 1
If (linenum Mod 2) = 0) Then
html += Chr(13) & "<tr class=""openrow2"">"
Else
html += Chr(13) & "<tr class=""openrow1"">"
End If
....
Loop
So what the issue is, i have 2 for loops one nested within another. The outer loop calling a procedure, the inner loop setting a attribute for the procedure to use. The problem is that the procedure is that I wan't to exit the loop use the pos <-- attribute call the procedure and re-enter the inner loop. At the minute the pos is only being set once because all the conditions are true within the inner loop meaning that its being replaced each time. I want to be able to set the pos exit the inner loop, call the procedure and re-enter the inner loop and set it pos to a different value? any help would be great!! here is the code
For Each val As String In vals
If creditPoints = "20" And semester = "1" And year = "Year 1" Then
For Each position In MyPosList
If position.strLabel = "a1" And available(0) <> "False" Then
pos = position.strX & " " & position.strY
count += 1
available(0) = blnavailable
ElseIf position.strLabel = "b1" And available(1) <> "False" Then
pos = position.strX & " " & position.strY
count += 1
available(1) = blnavailable
Next
shortfat(semester, pos, creditPoints, title, year, modStatus, count)
End If
next
Are you just looking to break out of the inner loop when one of those conditions are met? If so, that's what the Exit keyword is for. You really should also set a flag to sanity check yourself, too.
''//Flag so that we know if we actually found a position
Dim FoundPosition as Boolean
For Each val As String In vals
''//Reset the flag and assume that are conditions are met
FoundPosition = False
If creditPoints = "20" And semester = "1" And year = "Year 1" Then
For Each position In MyPosList
If position.strLabel = "a1" And available(0) <> "False" Then
pos = position.strX & " " & position.strY
count += 1
available(0) = blnavailable
''//Flag that our conditions are met
FoundPosition = True
''//Exit from the inner loop
Exit For
ElseIf position.strLabel = "b1" And available(1) <> "False" Then
pos = position.strX & " " & position.strY
count += 1
available(1) = blnavailable
''//Flag that our conditions are met
FoundPosition = True
''//Exit from the inner loop
Exit For
End If
Next
''//Sanity check to ensure that our conditions are met
If FoundPosition Then
shortfat(semester, pos, creditPoints, title, year, modStatus, count)
Else
''//Do something here, either Throw an error or safely handle this case otherwise
End If
End If
Next
"I want to be able to set the pos exit the inner loop, call the
procedure and re-enter the inner loop and set it pos to a different
value?"
Things like that are better served with a WHILE loop than a FOR loop.
Just a stab in the dark here, but it sounds like you want to be able to see if shortfat is producing a favorable value. And if it does not, you want it to recompute pos. The first thing I'd do, is alter shortfat to return some kind of value...for my example, I'll have it return a boolean.
Dim blnDidThisDoWhatIWant As Boolean
For Each val As String In vals
If creditPoints = "20" And semester = "1" And Year() = "Year 1" Then
blnDidThisDoWhatIWant = False
While blnDidThisDoWhatIWant = False
For Each position In MyPosList
If position.strLabel = "a1" And available(0) <> "False" Then
pos = position.strX & " " & position.strY
count += 1
available(0) = blnavailable
ElseIf position.strLabel = "b1" And available(1) <> "False" Then
pos = position.strX & " " & position.strY
count += 1
available(1) = blnavailable
End If
Next
blnDidThisDoWhatIWant = shortfat(semester, pos, creditPoints, title, Year, modStatus, count)
End While
End If
Next
This will allow you to re-enter the inner loop. The problem is that it'll be infinite unless pos is computed differently (which I don't see how it can). So that's something you'll have to work out on your own. Hope this helps point you in the right direction.