Jump to content
Sign in to follow this  
Leonick

Simple Dialogbox works only the frist time.

Recommended Posts

Leonick

Hey guys...

this is not the first time i am encountering the problem when working in: Opt("GUIOnEventMode", 1)

A simple dialogbox that asks if you really wanna quit after pressing "ESC".

The first time it works as preticted,...but the second time not.

I am missing something...i know.

thx in advance

code
#include <Timers.au3>
#include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>
#include <GDIPlus.au3>
#include <string.au3>
#include <Constants.au3>
#include <Array.au3>
#include <StaticConstants.au3>
#include <ButtonConstants.au3>


HotKeySet("{esc}", "_Quit")
Opt("GUIOnEventMode", 1)


Global $exitgui


main()

Func Main()
    While 1
        Sleep(100)
    WEnd
EndFunc   ;==>Main




Func _Quit()

    $exitgui = GUICreate("Custom Msgbox", 210, 80)

    GUICtrlCreateLabel("Really quit?", 10, 10)
    $YesID = GUICtrlCreateButton("Yes", 10, 50, 50, 20)
    GUICtrlSetOnEvent($YesID, "OnYes")
    $NoID = GUICtrlCreateButton("No", 80, 50, 50, 20)
    GUICtrlSetOnEvent($NoID, "OnNo")
    
    GUISetState() ; display the GUI

    While 1
        Sleep(1000)
    WEnd
EndFunc   ;==>_Quit


Func OnYes()
    exit
EndFunc   ;==>OnYes

Func OnNo()
    GUIDelete($exitgui)
    Main()
EndFunc   ;==>OnNo

Share this post


Link to post
Share on other sites
Melba23

Leonick,

You have too many While...WEnd loops, but most importantly, you call your Main() function recursively.

1. While...WEnd loops. You do not need a While...WEnd loop in func _Quit(). Once the function is called, it creates the message box and then control reverts to the While...WEnd loop in func Main(). By adding an additional loop you will never return from _Quit(). Try running this modified code to see what I mean - leave it to run for a few seconds to get a few "Main loop" returns and then press "ESC" and see what happens to the returns. :(

; This code is only for demo purposes

#include <Timers.au3>
#include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>
#include <GDIPlus.au3>
#include <string.au3>
#include <Constants.au3>
#include <Array.au3>
#include <StaticConstants.au3>
#include <ButtonConstants.au3>

HotKeySet("{esc}", "_Quit")
Opt("GUIOnEventMode", 1)

Global $exitgui

main()

Func Main()
    While 1
        Sleep(1000)
        ConsoleWrite("In the Main loop" & @CRLF)
    WEnd
EndFunc   ;==>Main

Func _Quit()

    $exitgui = GUICreate("Custom Msgbox", 210, 80)

    GUICtrlCreateLabel("Really quit?", 10, 10)
    $YesID = GUICtrlCreateButton("Yes", 10, 50, 50, 20)
    GUICtrlSetOnEvent($YesID, "OnYes")
    $NoID = GUICtrlCreateButton("No", 80, 50, 50, 20)
    GUICtrlSetOnEvent($NoID, "OnNo")

    GUISetState() ; display the GUI

    While 1
        Sleep(1000)
        ConsoleWrite("In the Quit loop" & @CRLF)
    WEnd
EndFunc   ;==>_Quit


Func OnYes()
    exit
EndFunc   ;==>OnYes

Func OnNo()
    GUIDelete($exitgui)
    ;Main()
EndFunc   ;==>OnNo

2. Func Main() calls. But the main problem was that you were calling func Main() from within func OnNo() - not a good idea as you are already in that function waiting for events to happen!! >_< Reentering functions like that is not recommended - unless you are very careful and really need to (it is one way to code a recursive search, for example). You will return to Main() automatically once OnNo() ends - there is no need to call it again.

So to work correctly your code should read:

; This code does what you want

#include <Timers.au3>
#include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>
#include <GDIPlus.au3>
#include <string.au3>
#include <Constants.au3>
#include <Array.au3>
#include <StaticConstants.au3>
#include <ButtonConstants.au3>

HotKeySet("{esc}", "_Quit")
Opt("GUIOnEventMode", 1)

Global $exitgui

main()

Func Main()
    While 1
        Sleep(1000)
    WEnd
EndFunc   ;==>Main

Func _Quit()

    $exitgui = GUICreate("Custom Msgbox", 210, 80)

    GUICtrlCreateLabel("Really quit?", 10, 10)
    $YesID = GUICtrlCreateButton("Yes", 10, 50, 50, 20)
    GUICtrlSetOnEvent($YesID, "OnYes")
    $NoID = GUICtrlCreateButton("No", 80, 50, 50, 20)
    GUICtrlSetOnEvent($NoID, "OnNo")

    GUISetState() ; display the GUI

EndFunc   ;==>_Quit

Func OnYes()
    exit
EndFunc   ;==>OnYes

Func OnNo()
    GUIDelete($exitgui)
EndFunc   ;==>OnNo

M23


Any of my own code posted anywhere on the forum is available for use by others without any restriction of any kind._______My UDFs:

Spoiler

ArrayMultiColSort ---- Sort arrays on multiple columns
ChooseFileFolder ---- Single and multiple selections from specified path treeview listing
Date_Time_Convert -- Easily convert date/time formats, including the language used
ExtMsgBox --------- A highly customisable replacement for MsgBox
GUIExtender -------- Extend and retract multiple sections within a GUI
GUIFrame ---------- Subdivide GUIs into many adjustable frames
GUIListViewEx ------- Insert, delete, move, drag, sort, edit and colour ListView items
GUITreeViewEx ------ Check/clear parent and child checkboxes in a TreeView
Marquee ----------- Scrolling tickertape GUIs
NoFocusLines ------- Remove the dotted focus lines from buttons, sliders, radios and checkboxes
Notify ------------- Small notifications on the edge of the display
Scrollbars ----------Automatically sized scrollbars with a single command
StringSize ---------- Automatically size controls to fit text
Toast -------------- Small GUIs which pop out of the notification area

 

Share this post


Link to post
Share on other sites
Leonick

Woooooooooooooow thx melba...... :(:(

I already have written a very complex script with several thousands lines,....but now I think i understood to 80% a very basic and very important thing.

BIG big thx for explaining. >_<

But I dont get it to 100%.

the Problem was:

code
Func OnNo()
    GUIDelete($exitgui)
    Main()
EndFunc   ;==>OnNo

since it would go there automaticly.

but what if i wanna continue to another mainfunction, that got a loop as well.

e.g. function2()

Why should i not go back to main() like that?

(I felt before, from very inside, that this is bad,..but still don't get it)

....not a good idea as you are already in that function waiting for events to happen!!

You mean because the main() is waiting for something?? Edited by Leonick

Share this post


Link to post
Share on other sites
Melba23

Leonick,

When you run any script, there a comes a point when you are waiting for input. If you are in MessageLoop mode, it is here you see what GUIGetMsg returns; if in OnEvent mode, you just idle about waiting for events to trigger. Of interest, that is why you need a Sleep(10) in the loop when in OnEvent mode - otherwise the tight loop just gobbles up CPU. In MessageLoop mode, GUIGetMsg does that job for you - as the Help file explains.

So you are in your loop (func Main() in your case) and an event is triggered. The loop is paused and AutoIt goes off and does whatever the event function wants. Once the event function is over, the main loop resumes. What you were doing was calling Main() again, thus starting a new loop - if you did this often enough you would max out the system as it would have too many paused Main() functions to keep track of.

If you want to run another function before returning to Main(), then AutoIt merely pauses the running event function and starts the new function. Once this function is finished, the paused event function restarts and when it is itself finished, returns control to Main(). There is not a problem if this function has a loop within it, as long as there is a way of escaping from it and exiting the function eventually. You must get back to your Main() loop each time an event function is triggered - which means every function used must exit at some point so that control can cascade back to the idle loop.

The thing to avoid is running functions inside themselves (known as recursion) unless you want to and you know what you are doing. As I said before, a recursive file search (where you search in the subfolders you find as you search) is a good example where recursion can work, as are many sorting functions. Usually the difficulty comes when you get inadvertant recursion (as was the case here) which can lead to some strange behaviour which is not readily diagnosed.

I hope that is clear.

M23


Any of my own code posted anywhere on the forum is available for use by others without any restriction of any kind._______My UDFs:

Spoiler

ArrayMultiColSort ---- Sort arrays on multiple columns
ChooseFileFolder ---- Single and multiple selections from specified path treeview listing
Date_Time_Convert -- Easily convert date/time formats, including the language used
ExtMsgBox --------- A highly customisable replacement for MsgBox
GUIExtender -------- Extend and retract multiple sections within a GUI
GUIFrame ---------- Subdivide GUIs into many adjustable frames
GUIListViewEx ------- Insert, delete, move, drag, sort, edit and colour ListView items
GUITreeViewEx ------ Check/clear parent and child checkboxes in a TreeView
Marquee ----------- Scrolling tickertape GUIs
NoFocusLines ------- Remove the dotted focus lines from buttons, sliders, radios and checkboxes
Notify ------------- Small notifications on the edge of the display
Scrollbars ----------Automatically sized scrollbars with a single command
StringSize ---------- Automatically size controls to fit text
Toast -------------- Small GUIs which pop out of the notification area

 

Share this post


Link to post
Share on other sites
Leonick

YES...that was very clear. :(

This should be in the help section,..as starting basics.(Maybe i overlocked it, or was explained only in a sidenote)

I did this 95% right in my script till now,...but i am lucky, that i can correct them, and prevent further strange behaviour.

I am very thankful melba. >_<

Edited by Leonick

Share this post


Link to post
Share on other sites
Leonick

Ok after trying to correct my huge script, there are arising several problems....an i am feeling like my first day with autoit.

how can you do this?

code
HotKeySet("{F1}", "_FunctionF1")
Opt("GUIOnEventMode", 1)





Main()

Func Main()
    While 1
        Sleep(100)
        ;--stuff
        functionTest1()
    WEnd
EndFunc   ;==>Main



Func functionTest1()
    while 1
;----stuff
;----calling other funtions and coming back
     functionTest2()
;----stuff
    wend
EndFunc   ;==>function1


func functionTest2()
    ;--doing stuff
    ;---!!!!!!!!!!!!!!!! NOW F1 GET PRESSED!!!!!!!!!!!!!!!
    
EndFunc

func functionF1
    ;--PROGRAM DECIDING ACCORDING TO GUI VARIABLES AND/OR .INI DATA THAT IT WANTS BACK TO MAIN()
    ;--now i cannot do
    main() ;-?????
EndFunc

Now i really feel lost,....since the way above was working fine till now

Before autoit i knew qbasis,..and I was working with "GOTO lineXY"

but now?

I cannot jump from one function to another and back to main,..without letting the functions end?

Share this post


Link to post
Share on other sites
Melba23

Leoick,

Do NOT get discouraged - not having GOTO is very hard to cope with at first, but it becomes easier after a while.

Personally I always use MessageLoop mode for my main GUI and TrayOnEvent for the tray icon. Why? Using GUIGetMsg means I always return to my main While..WEnd loop without interruption (except by Tray events and these can be blocked easily for a short period if required). It also allows me to pass parameters to the functions I call - with OnEvent mode this cannot be done except by using martin's UDF.

But coming to AutoIt from a GOTO language does take a bit of readjustment - I had to completely rethink the way I coded. I am pretty certain you will have to do the same. :( I have added comments to your sample to try and explain a bit more:

code
HotKeySet("{F1}", "_FunctionF1")
Opt("GUIOnEventMode", 1)

; F1 can get pressed at any time in this loop and it will interrupt and run
While 1
    Sleep(100)
    ;--stuff
    functionTest1()
WEnd

Func functionTest1()
    While 1 ; Will you be able to get out of this loop at some time?
    ;----stuff
    ;----calling other functions and returning
     functionTest2() ; No problem here
    ;----stuff
    WEnd
EndFunc   ;==>function1

func functionTest2()
    ;--doing stuff
EndFunc

func functionF1
    ;--PROGRAM DECIDING ACCORDING TO GUI VARIABLES AND/OR .INI DATA THAT IT WANTS BACK TO MAIN()
    ;
    ; So here you can change variables etc to be actioned when this function is over
    ;
    ;main() ;-????? 
    ; Definitely NOT needed as control will return to wherever the script was paused when this function finishes
    ; If you call main() you will get the unintended recursion I spoke of earlier
EndFunc

But I am sorry to say that you will just have to relearn how to code again in the AutoIt style! However, I do believe it is worth it - you have an excellent language and these very helpful forums to aid you as you learn.... >_<

Good luck.

M23


Any of my own code posted anywhere on the forum is available for use by others without any restriction of any kind._______My UDFs:

Spoiler

ArrayMultiColSort ---- Sort arrays on multiple columns
ChooseFileFolder ---- Single and multiple selections from specified path treeview listing
Date_Time_Convert -- Easily convert date/time formats, including the language used
ExtMsgBox --------- A highly customisable replacement for MsgBox
GUIExtender -------- Extend and retract multiple sections within a GUI
GUIFrame ---------- Subdivide GUIs into many adjustable frames
GUIListViewEx ------- Insert, delete, move, drag, sort, edit and colour ListView items
GUITreeViewEx ------ Check/clear parent and child checkboxes in a TreeView
Marquee ----------- Scrolling tickertape GUIs
NoFocusLines ------- Remove the dotted focus lines from buttons, sliders, radios and checkboxes
Notify ------------- Small notifications on the edge of the display
Scrollbars ----------Automatically sized scrollbars with a single command
StringSize ---------- Automatically size controls to fit text
Toast -------------- Small GUIs which pop out of the notification area

 

Share this post


Link to post
Share on other sites
Leonick

hey you again >_<

Personally I always use MessageLoop mode for my main GUI and TrayOnEvent for the tray icon. Why? Using GUIGetMsg means I always return to my main While..WEnd loop without interruption

I was thinking about to use this method from now on,..after your previous post.

code
;main()

"Definitely NOT needed as control will return to wherever the script was paused..."

control? what do you mean by control?

I know that i can work with...."return" and setting/checking varables to come back to main,...without continuing functionTest2() as you can see in my WORKING code.

code
HotKeySet("{F1}", "_FunctionF1")
Opt("GUIOnEventMode", 1)

main()

func main()
While 1
    Sleep(1000)
    ConsoleWrite("main()"&@lf)
    functionTest1()
WEnd
endfunc

Func functionTest1()
    for $n=1 to 100
    ConsoleWrite("a"&@lf)
    Sleep(1000)
    ConsoleWrite("b"&@lf)
    Sleep(1000)
    ConsoleWrite("c"&@lf)
    Sleep(1000)
    ConsoleWrite("d"&@lf)
    Sleep(1000)
    functionTest2()
    If functionTest2()=false then Return ;--back to main()  -----or even "exitloop" would work as well
    ConsoleWrite("e"&@lf)
    Sleep(1000)
    ConsoleWrite("f"&@lf)
    Sleep(1000)
    ConsoleWrite("g"&@lf)
    Sleep(1000)
    ConsoleWrite("h"&@lf)
   next
EndFunc   ;==>function1

func functionTest2()
    ConsoleWrite("functionTest2"&@lf)
    sleep(1000)
    return false ;-----Function decides to go back to main() so therefore it return false e.g.
EndFunc

func _functionF1()
    ConsoleWrite("functionF1"&@lf)
    ;-----function wants to go back to mainloop without going back to functionTest1() and continuing...how????
return
EndFunc

But how can i come back to main() if "F1" is pressed while in functionTest2() after the letter "c" (e.g.)?????

looool.....

(I have like 50 funtions in my script till now,...many with loops and some still rekursiv....its working, but i wanna learn the right way.)

Share this post


Link to post
Share on other sites
Melba23

Leonick,

"Definitely NOT needed as control will return to wherever the script was paused..."

control? what do you mean by control?

I mean that the script will resume running from the point it was interrupted.

As to interrupting a running function in the way you require - one of AutoIt's particuliarities is that a script will always return to the point it was interrupted and continue running from that point. In MessageLoop mode, GUIGetMsg creates a stack of returned ControlIDs and then runs them when it can - in OnEvent mode the script runs the Event function and then resumes what it was doing before. Of course, this behaviour is not necessarily a limitation - it allows functions like HotKeySet and Adlib to function and many of us would be very unhappy to lose them!

That is why I said in an earlier post that it requires a different approach to coding when you no longer have the GOTO function. Having made the transition, I am firmly of the camp that believes removing GOTO makes for better, more structured coding - although I found it quite difficult at first. if you are trying to port code directly from GOTO languages to AutoIt, you are likely to find it very frustrating. The best advice I can give is to think carefully about what it is you want your code to do (I find writing down a logic flow diagram a very useful exercise) and then restructure your code to fit how Autoit functions. Believe me, AutoIt can certainly cope with whatever you want it do - the trick is to work with it and not against it!

As an example of how you need to think differently, here is your code modified so that it will allow you to return from functionTest1 whenever you press the HotKey. It requires a bit more coding as you can see, but it does what you want. You could further refine it by putting the timer/flagcheck loop into a separate function - but I will leave you to play with that idea!

;code
HotKeySet("{F1}", "_FunctionF1")
Opt("GUIOnEventMode", 1)

Global $fFlag ; Must be Global so all functions can see and use it

main()

Func main()
    While 1
        Sleep(1000)
        ConsoleWrite("main()" & @LF)
        functionTest1()
    WEnd
EndFunc   ;==>main

Func functionTest1()
    $fFlag = False
    For $n = 1 To 100
        ConsoleWrite("a" & @LF)
        $nBegin = TimerInit()
        While TimerDiff($nBegin) < 1000
            If $fFlag = True Then Return
        WEnd
        ConsoleWrite("b" & @LF)
        $nBegin = TimerInit() ; Start a timer
        While TimerDiff($nBegin) < 1000 ; while timer is less that 1000 msec
            If $fFlag = True Then Return ; If functionF1 has set the flag -return
        WEnd
        ConsoleWrite("c" & @LF)
        $nBegin = TimerInit()
        While TimerDiff($nBegin) < 1000
            If $fFlag = True Then Return
        WEnd
        ConsoleWrite("d" & @LF)
        $nBegin = TimerInit()
        While TimerDiff($nBegin) < 1000
            If $fFlag = True Then Return
        WEnd
        ; Do not need 2 calls to functionTest2 here
        If functionTest2() = False Then Return ;--back to main()  -----or even "exitloop" would work as well
        ConsoleWrite("e" & @LF)
        $nBegin = TimerInit()
        While TimerDiff($nBegin) < 1000
            If $fFlag = True Then Return
        WEnd
        ConsoleWrite("f" & @LF)
        $nBegin = TimerInit()
        While TimerDiff($nBegin) < 1000
            If $fFlag = True Then Return
        WEnd
        ConsoleWrite("g" & @LF)
        $nBegin = TimerInit()
        While TimerDiff($nBegin) < 1000
            If $fFlag = True Then Return
        WEnd
        ConsoleWrite("h" & @LF)
    Next
EndFunc   ;==>functionTest1

Func functionTest2()
    ConsoleWrite("functionTest2" & @LF)
    Sleep(1000)
    Return False ;-----Function decides to go back to main() so therefore it return false e.g.
EndFunc   ;==>functionTest2

Func _functionF1()
    ConsoleWrite("functionF1" & @LF)
    $fFlag = True
    ;-----function wants to go back to mainloop without going back to functionTest1() and continuing - and now it does!!!!!!!!!!!!!
    Return
EndFunc   ;==>_functionF1

Enough tuition for now. Good luck with your coding!

M23


Any of my own code posted anywhere on the forum is available for use by others without any restriction of any kind._______My UDFs:

Spoiler

ArrayMultiColSort ---- Sort arrays on multiple columns
ChooseFileFolder ---- Single and multiple selections from specified path treeview listing
Date_Time_Convert -- Easily convert date/time formats, including the language used
ExtMsgBox --------- A highly customisable replacement for MsgBox
GUIExtender -------- Extend and retract multiple sections within a GUI
GUIFrame ---------- Subdivide GUIs into many adjustable frames
GUIListViewEx ------- Insert, delete, move, drag, sort, edit and colour ListView items
GUITreeViewEx ------ Check/clear parent and child checkboxes in a TreeView
Marquee ----------- Scrolling tickertape GUIs
NoFocusLines ------- Remove the dotted focus lines from buttons, sliders, radios and checkboxes
Notify ------------- Small notifications on the edge of the display
Scrollbars ----------Automatically sized scrollbars with a single command
StringSize ---------- Automatically size controls to fit text
Toast -------------- Small GUIs which pop out of the notification area

 

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  

×