Sign in to follow this  
Followers 0
arkane

[Solved, Thx] Start / Stop button, and a loop

27 posts in this topic

#1 ·  Posted (edited)

Hi, I've posted a similar topic in an another section, but I guess it wasn't the best one to talk in. So I prefer repost it here.

My problem is that, I've created 2 buttons. One start, one stop.

When I clic start, it's supposed to execute a few functions, but when I hit Stop, I want it to act as an "ExitLoop".

My issue is that in one of my functions, there are many loops, like do-untile, while 1...

Here is a minimal exemple I made so you can see what I'm talking about :

#include <GuiConstantsEx.au3>
#include <WindowsConstants.au3>
Opt("GUIOnEventMode", 1) 
Opt("SendKeyDownDelay", 25)
Opt("MouseClickDownDelay", 50)

$BotFenetre = GUICreate(".: Test 2 :.", 300, 325, 0, 0, -1, $WS_EX_TOPMOST)
$Start = GUICtrlCreateButton("Start", 80, 280, 50, 20)
GUICtrlSetOnEvent($Start, "ActiverJoueur")
$Stop = GUICtrlCreateButton("Stop", 160, 280, 50, 20)
GUICtrlSetOnEvent($Stop, "Quitter")
GUISetOnEvent($GUI_EVENT_CLOSE, "Quitter")
GUISetState(@SW_SHOW)

While 1
    $msg = GUIGetMsg(1)
    Select
        Case $msg[0] = $GUI_EVENT_CLOSE
                If $msg[1] = $BotFenetre Then
                    GUISwitch($BotFenetre)
                    GUIDelete()
                    Exit
                EndIf
                    
        Case $msg[0] = $GUI_EVENT_CLOSE         
            If $msg[1] = $BotFenetre Then
                GUISwitch($BotFenetre)
                GUIDelete()
                Exit
            EndIf

        Case $msg[0] = $Start
            ActiverJoueur()
    EndSelect       
WEnd

Func Quitter()
    GUIDelete()
    Exit
EndFunc
    
Func TuerPorteur()
    ;~  On sprint
    Send("{z down}")
    sleep(30)
    Send("{z up}")
    sleep(30)
    Send("{z down}")
    sleep(7400)
    Send("{z up}")

    ;~  On tue
    Send("{q down}")
    sleep(150)
    Send("{q up}")
    MouseDown("left")
    sleep(4000)
    MouseUp("left")
EndFunc

Func ActiverJoueur()
    While 1
        $msg = GUIGetMsg(1)
        Select
        Case $msg[0] = $Stop
            ExitLoop
        EndSelect
        
        ;~  On se met pret
        MouseClick("left", 636, 896, 1, 0)
        sleep(2500) 
        
        ;~  On va tuer le porteur
        TuerPorteur()
    WEnd
EndFunc

I need that button to stop my code, no matter where I actualy am in the evolving of my code, which function I'm executing.

Do you have any idea ?

Sorry for my english btw.

Enjoy, and happy 2010 ;).

Edited by arkane

Share this post


Link to post
Share on other sites



#3 ·  Posted (edited)

Thanks for you answer. I did try the following :

#include <GuiConstantsEx.au3>
#include <WindowsConstants.au3>
Opt("GUIOnEventMode", 1) 
Opt("SendKeyDownDelay", 25)
Opt("MouseClickDownDelay", 50)

$BotFenetre = GUICreate(".: Test 2 :.", 300, 325, 0, 0, -1, $WS_EX_TOPMOST)
$Start = GUICtrlCreateButton("Start", 80, 280, 50, 20)
GUICtrlSetOnEvent($Start, "ActiverJoueur")
$Stop = GUICtrlCreateButton("Stop", 160, 280, 50, 20)
GUICtrlSetOnEvent($Stop, "Quitter")
GUISetOnEvent($GUI_EVENT_CLOSE, "Quitter")
GUISetState(@SW_SHOW)

AdlibRegister ("checkstop")

Func checkstop()
    $msg = GUIGetMsg(1)
    Select
    Case $msg[0] = $Stop
        ExitLoop
    EndSelect
    
EndFunc

While 1
    $msg = GUIGetMsg(1)
    Select
        Case $msg[0] = $GUI_EVENT_CLOSE
                If $msg[1] = $BotFenetre Then
                    GUISwitch($BotFenetre)
                    GUIDelete()
                    Exit
                EndIf
                    
        Case $msg[0] = $GUI_EVENT_CLOSE         
            If $msg[1] = $BotFenetre Then
                GUISwitch($BotFenetre)
                GUIDelete()
                Exit
            EndIf

        Case $msg[0] = $Start
            ActiverJoueur()
    EndSelect       
WEnd

Func Quitter()
    GUIDelete()
    AdlibUnRegister("checkstop")
    Exit
EndFunc
    
Func TuerPorteur()
    ;~  On sprint
    Send("{z down}")
    sleep(30)
    Send("{z up}")
    sleep(30)
    Send("{z down}")
    sleep(7400)
    Send("{z up}")

    ;~  On tue
    Send("{q down}")
    sleep(150)
    Send("{q up}")
    MouseDown("left")
    sleep(4000)
    MouseUp("left")
EndFunc

Func ActiverJoueur()
    While 1
        ;~  On se met pret
        MouseClick("left", 636, 896, 1, 0)
        sleep(2500) 
        
        ;~  On va tuer le porteur
        TuerPorteur()
    WEnd
EndFunc

But it returns me this error : ""ExitLoop/ContinueLoop" statements only valid from inside a For/Do/While loop"

Edit : I also tried to put my checkstop function into a while 1 loop, then it launchs, but the stop button still doesn't work.

Edited by arkane

Share this post


Link to post
Share on other sites

You mixed up GUIGetMsg() and GUIOnEventMode ;), re-read the help-file on those two :evil: ...

#include <GuiConstantsEx.au3>
#include <WindowsConstants.au3>

Opt("GUIOnEventMode", 1)
Opt("SendKeyDownDelay", 25)
Opt("MouseClickDownDelay", 50)

Global $bBreak = False

$BotFenetre = GUICreate(".: Test 2 :.", 300, 325, 0, 0, -1, $WS_EX_TOPMOST)
GUISetOnEvent($GUI_EVENT_CLOSE, "Quitter")

$Start = GUICtrlCreateButton("Start", 80, 280, 50, 20)
GUICtrlSetOnEvent($Start, "ActiverJoueur")
$Stop = GUICtrlCreateButton("Stop", 160, 280, 50, 20)

$cLabel_Status = GUICtrlCreateLabel("Idle...",10,10,100,20)

GUISetState(@SW_SHOW)

GUIRegisterMsg($WM_COMMAND,"WM_COMMAND")

While sleep(10)
WEnd

Func Quitter()
    GUIDelete()
    Exit
EndFunc   ;==>Quitter

Func ActiverJoueur()
    GUICtrlSetData($cLabel_Status,"Running...")
    $bBreak = False
    While 1
        MouseClick("left", 636, 896, 1, 0)
        if $bBreak = True then ExitLoop
        if _Sleep(2500) = 1 then ExitLoop
        TuerPorteur()
    WEnd
    GUICtrlSetData($cLabel_Status,"Idle...")
EndFunc   ;==>ActiverJoueur

Func TuerPorteur()
;~  On sprint
    Send("{z down}")
    if _Sleep(30) = 1 then Return
    Send("{z up}")
    if _Sleep(30) = 1 then Return
    Send("{z down}")
    if _Sleep(7400) = 1 then Return
    Send("{z up}")
;~  On tue
    Send("{q down}")
    if _Sleep(150) = 1 then Return
    Send("{q up}")
    MouseDown("left")
    if _Sleep(4000) = 1 then Return
    MouseUp("left")
EndFunc   ;==>TuerPorteur

Func _sleep($sleeptime)
    $timer = TimerInit()
    while TimerDiff($timer) < $sleeptime
        sleep(10)
        if $bBreak then Return 1
    wend
    Return 0
EndFunc

Func WM_COMMAND($hWnd, $Msg, $wParam, $lParam)
    Local $iIDFrom = BitAND($wParam, 0xFFFF) ;LoWord
    ; Local $iCode = BitShift($wParam, 16) ;HiWord
    Switch $iIDFrom
        Case $Stop
            $bBreak = True
    EndSwitch
EndFunc

Share this post


Link to post
Share on other sites

#5 ·  Posted (edited)

How about just setting a global variable flag that you test in the loop?

Edited by PhilHibbs

Share this post


Link to post
Share on other sites

Thanks a lot KaFu !

I'm not understanding everything in your correction, but I'm taking a deep look in it. Thanks again.

Let my ask you something else please ;) : Do you know why when I do :

Send("{z down}")

if _Sleep(7400) = 1 then Return

Send("{z up}")

It doesn't really work the same for everybody ? I mean, let's imagine that Z key makes a character walk forward. So you start from an "A" point, and wants to reach a "Z" point" by pressing Z for 7,4 seconds.

Do you know why for some people, it will make the character go further ?

Share this post


Link to post
Share on other sites

Do you know why for some people, it will make the character go further ?

The game runs/polls the keyboard faster/slower on different computers due to their computing power?

Share this post


Link to post
Share on other sites

#8 ·  Posted (edited)

So it means that milliseconds arn't the same for everybody ? Anyway to make this work a little better ?

Maybe by increasing the sendkeydown delay ?

Edit : Btw, I found a small issue to your correction. When you press "stop" , you can't launch the script anymore.

Edited by arkane

Share this post


Link to post
Share on other sites

#9 ·  Posted (edited)

So it means that milliseconds arn't the same for everybody ? Anyway to make this work a little better ?

No, you should base the movement of the character on the time elapsed, not the other way around (we did this in the 1980s and it sucked ). Edited by Manadar

Share this post


Link to post
Share on other sites

So it means that milliseconds arn't the same for everybody ? Anyway to make this work a little better ?

The milliseconds are the same ;), just that one computer polls the keyboard 10.000 times a second and another only 9.800 times. How about sending multiple single keystrokes instead of holding the keys down?

Edit : Btw, I found a small issue to your correction. When you press "stop" , you can't launch the script anymore.

Really? Tried it and it worked fine for me...

Share this post


Link to post
Share on other sites

#11 ·  Posted (edited)

The milliseconds are the same ;), just that one computer polls the keyboard 10.000 times a second and another only 9.800 times. How about sending multiple single keystrokes instead of holding the keys down?

Bah, In fact, for what I want to do, you have to hold down a key : Pressing z twice, but holding the second press will make a character run faster.

Really? Tried it and it worked fine for me...

And it finally seems to work, I probably did a mistake somewhere while trying to understand it :evil:.

Edited by arkane

Share this post


Link to post
Share on other sites

It's definitely working great. I addapted the whole thing to my 400 lines code... Took a while but worth it !

I need a last help, and then I'll be done ;).

Do you know how can I do to activate a button with a key ?

I mean, I would like for example to set F1, to stop the script.

I tried the ControlClick function, which works, but not when the script is launched so it's useless.

Do you have any clue ?

Thanks again.

Share this post


Link to post
Share on other sites

I mean, I would like for example to set F1, to stop the script.

You want to use HotKeySet ;)

HotKeySet("[i]{KEY TO USE}[/i]","ExitProg")

Func ExitProg()
   Exit()
EndFunc

Share this post


Link to post
Share on other sites

#14 ·  Posted (edited)

Share this post


Link to post
Share on other sites

#15 ·  Posted (edited)

GUISetAccelerator() doesn't work if it hasn't the focus.

Hotsetkey neighter. I tried :

HotKeySet("{F1}", "FocusProg")

...

Func FocusProg()
    WinActivate($bot)
    ControlFocus($bot, "", "[CLASS:Button; INSTANCE:4]")
    ControlClick($bot, "", "[CLASS:Button; INSTANCE:4]")
EndFunc

But it doesn't work once the script has started (manual click still works indeed).

$bot is the title of the window of my program.

Edited by arkane

Share this post


Link to post
Share on other sites

GUISetAccelerator() doesn't work if it hasn't the focus.

Hotsetkey neighter. I tried :

HotKeySet("{F1}", "FocusProg")

...

Func FocusProg()
    WinActivate($bot)
    ControlFocus($bot, "", "[CLASS:Button; INSTANCE:4]")
    ControlClick($bot, "", "[CLASS:Button; INSTANCE:4]")
EndFunc

But it doesn't work once the script has started (manual click still works indeed).

$bot is the title of the window of my program.

Try a ConsoleWrite("working") or MsgBox(0,"hi","It's working") in your FocusProg() function to see if the function is getting called at all. If it's not, it could be that your game is reserving the F1 key (even if it's not actually using it).

"There are 10 types of people in this world - those who can read binary, and those who can't.""We've heard that a million monkeys at a million keyboards could produce the complete works of Shakespeare; now, thanks to the Internet, we know that is not true." ~Robert Wilensky0101101 1001010 1100001 1101101 1100101 1110011 0110011 1001101 10001110000101 0000111 0001000 0001110 0001101 0010010 1010110 0100001 1101110

Share this post


Link to post
Share on other sites

#17 ·  Posted (edited)

I tried with a messagebox.

It doesn't work. It's not called once I launched the script.

I use : F5 to launch one script, using _isPressed, F6 for an another.

While sleep(10)
        ;F5
        if _IsPressed("74", $dll) then
            ActiverMaster()
        endif
        ;F6
        if _IsPressed("75", $dll) then
            ActiverJoueur()
        endif
        HotKeySet("{F1}", "FocusProg")
    WEnd
    DllClose($dll)

...

Func FocusProg()
    WinActivate($bot)
    ControlFocus($bot, "", "[CLASS:Button; INSTANCE:4]")
    ControlClick($bot, "", "[CLASS:Button; INSTANCE:4]")
    MsgBox(0,"hi","It's working")
EndFunc

Once I press F5 or F6, the script go into the called function. So I can't press f5 or f6 one more time unless I press stop, which is normal. But HotKeySet is supposed to interrupt everything and have priority, that's what is written in the help file.

The issue is not with f1. I did try F5 too, which work with isPressed, but it doesn't.

Edited by arkane

Share this post


Link to post
Share on other sites

I tried with a messagebox.

It doesn't work. It's not called once I launched the script.

What is the return value from your call to HotKeySet()?

"There are 10 types of people in this world - those who can read binary, and those who can't.""We've heard that a million monkeys at a million keyboards could produce the complete works of Shakespeare; now, thanks to the Internet, we know that is not true." ~Robert Wilensky0101101 1001010 1100001 1101101 1100101 1110011 0110011 1001101 10001110000101 0000111 0001000 0001110 0001101 0010010 1010110 0100001 1101110

Share this post


Link to post
Share on other sites

#19 ·  Posted (edited)

Edit : I was wrong. It works.

But in fact, my GUI needs to have the focus : my WinActivate in FocusProg() doesn't seems to work correctly.

It works if everything but my game got the focus... no matter what Key I choose.

Do you have any idea why ?

Edit 2 : Note that the issue seems to come from Hotsetkey, which isn't reacting if my game got the focus.

I replaced

HotKeySet("{F1}", "FocusProg")

by

if _IsPressed("70", $dll) then FocusProg()

And it works from the game. But unfortunalty, I can't use _isPressed, because unlike Hotsetkey, it doesn't have priority over an another function.

So maybe you have an idea about how to give it priority, or maybe you know how to make hotsetkey react trough my game ;).

Thanks in advance.

Edited by arkane

Share this post


Link to post
Share on other sites

Anyone ? ;)

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!


Register a new account

Sign in

Already have an account? Sign in here.


Sign In Now
Sign in to follow this  
Followers 0