Jump to content

Wrong GUI Closes On Second Pass Through Script


Recommended Posts

Hello,

I'm relatively new to AutoIT having made a handful of scripts over the past couple of years. I was introduced to AutoIT by one of my co-workers.

I'm working on a script that triggers countdown timers on an external system (using UDP sockets--works great!) and triggers a local countdown timer (h/t to user Wakillon for the base of the countdowntimer script, which I've modified for my purposes).

The local timer part works fine from a countdown perspective. It counts down, reverts to the entry window, then counts down again when re-triggered.

In the case that someone enters the wrong time I have scripted the countdown timer to be "close-able" via a GUI_EVENT_CLOSE command, which then clears the timer (and the external system when fully functional), then returns to the entry interface.  This works great the first time...

The problem is that if I loop through this again, the attempt to close the countdown timer again--the second time it doesn't close the countdown window--instead, it waits for the countdown to finish then closes the entry window.

I've attached the code (instead of exiting I have message box popups to confirm which part of the script the GUI_EVENT_CLOSE is accessing).

So far I'm stumped. I've tried "GUISwitch", removing the old GUI, hiding/removing the countdown GUI, and everything else in between. I'm guessing this has something to do with interrupting the "While 1" loop in the "ComputercountDown()" function, but I haven't figured out a way to do that.

I've left my comments in line but removed the parts that "work".  the script does function (and, by extension fail) as has been copied here.  Hopefully this is clear. I'm sure the fix is probably something obvious.  Any advice would be appreciated.

Thanks!

 

EDIT FOR INTERNET.au3

Link to comment
Share on other sites

1 minute ago, radioguy said:

Hello,

I'm relatively new to AutoIT having made a handful of scripts over the past couple of years. I was introduced to AutoIT by one of my co-workers.

I'm working on a script that triggers countdown timers on an external system (using UDP sockets--works great!) and triggers a local countdown timer (h/t to user Wakillon for the base of the countdowntimer script, which I've modified for my purposes).

The local timer part works fine from a countdown perspective. It counts down, reverts to the entry window, then counts down again when re-triggered.

In the case that someone enters the wrong time I have scripted the countdown timer to be "close-able" via a GUI_EVENT_CLOSE command, which then clears the timer (and the external system when fully functional), then returns to the entry interface.  This works great the first time...

The problem is that if I loop through this again, the attempt to close the countdown timer again--the second time it doesn't close the countdown window--instead, it waits for the countdown to finish then closes the entry window.

I've attached the code (instead of exiting I have message box popups to confirm which part of the script the GUI_EVENT_CLOSE is accessing).

So far I'm stumped. I've tried "GUISwitch", removing the old GUI, hiding/removing the countdown GUI, and everything else in between. I'm guessing this has something to do with interrupting the "While 1" loop in the "ComputercountDown()" function, but I haven't figured out a way to do that.

I've left my comments in line but removed the parts that "work".  the script does function (and, by extension fail) as has been copied here.  Hopefully this is clear. I'm sure the fix is probably something obvious.  Any advice would be appreciated.

Thanks!

 

EDIT FOR INTERNET.au3 4.3 kB · 0 downloads

Sorry, I though the attachment would display the code.

;;Includes
#include <ButtonConstants.au3>
#include <EditConstants.au3>
#include <GUIConstantsEx.au3>
#include <GuiImageList.au3>
#include <GuiListView.au3>
#include <MsgBoxConstants.au3>
#include <StringConstants.au3>
#include <WinAPIFiles.au3>
#include <WindowsConstants.au3>

Global $SS_CENTER
Global $_CountdownTime
Global $_Minutes
Global $_Seconds
Global $TimeTicks
Global $TimeLabel
Global $_GuiCountDown
Global $EnterMinutes
Global $EnterSeconds
Global $StartButton
Global $Minutes
Global $Seconds
Global $_GuiEnterTime
Dim $aPanelCSV[0]

;Main function to trigger everything
Main()

Func Main()
    EnterTimeGUI()
    EnterTime()
EndFunc

Func PanelCount()
    ;stuff that works in the real script
EndFunc

;Primary function for entering in the countdown duration
Func EnterTimeGUI()
    ;;Create a GUI
    $_GuiEnterTime = GUICreate ( "Enter Start Time", 300, 150)
    Opt("GUIOnEventMode", 0)
    GUISetBkColor ( 0xFFFFFF )
    GUISetFont(10,0,0)
    $EnterLabel = GUICtrlCreateLabel ( "Minutes", 100,15,100,35)
    $EnterLabel = GUICtrlCreateLabel ( "Seconds", 160,15,100,35)
    GUISetFont(13.5,0,0)
    $EnterMinutes = GUICtrlCreateInput ("",105,35,45,35,$ES_NUMBER)
    $EnterSeconds = GUICtrlCreateInput ("",155,35,45,35,$ES_NUMBER)
    GUISetFont(12,0,0)
    $StartButton =     GUICtrlCreateButton    ("Start",110,80,80,50)
    GUISetState (@SW_SHOW,$_GuiEnterTime)
EndFunc

Func EnterTime()
    GUISetState (@SW_SHOW,$_GuiEnterTime)
    Opt("GUIOnEventMode", 0)
    While 1
        $MSG = GUIGetMsg()
        Select
            Case $MSG = $GUI_EVENT_CLOSE
                ;Exit
                MsgBox(4000,"DEBUG: Enter Time","enter time close button pressed")
            ;;Start button for countdown
            Case $MSG = $StartButton
                $Minutes = GUICtrlRead($EnterMinutes)
                $Seconds = GUICtrlRead($EnterSeconds)
                ;Math for the WallTime and local countdown functions
                 $Paneltime = (((60 * $Minutes) + $Seconds))
                 $_CountdownTime =(((60000 * $Minutes) + (1000 * $Seconds))+1000)
                Sleep(100)
                GUISetState (@SW_HIDE,$_GuiEnterTime)
                ;;Function starts the countdown timer on the WallTime panels
                PanelCountDown()
                ;;starts the function for local countdown
                CountDownGUI()
                ComputerCountDown()

        EndSelect
    WEnd
EndFunc

#cs
Local countdown--this was mostly taken from Wakillon's post in April of 2011, then modified for my use case. Full credit to Wakillon for this part.
https://www.autoitscript.com/forum/topic/127667-how-to-create-a-countdown-timer-in-autoit/
#ce

Func CountDownGUI()
;;Countdown GUI
    $_GuiCountDown = GUICreate ( "CountDown...", 500, 200, @DesktopWidth/2 -250, @DesktopHeight/2 -100)
    GUISwitch ($_GuiCountDown)
    Opt("GUIOnEventMode", 1)
    GUISetOnEvent($GUI_EVENT_CLOSE, "StopCountdown")
    GUISetBkColor ( 0xFFFFFF )
    $TimeLabel = GUICtrlCreateLabel ( "", 35, -10, 480, 180, $SS_CENTER )
    GUICtrlSetFont ( -1, 125, 800 )
    GUISetState (@SW_SHOW,$_GuiCountDown)
    ;WinSetOnTop ( $_GuiCountDown, "", 1 )
    $TimeTicks = TimerInit ( )
EndFunc

Func ComputerCountDown()
    While 1
        ;;calls the function to begin the countdown
        Check ( )
        Sleep (200)

    WEnd
EndFunc

Func Check ( )
    $_CountdownTime -= TimerDiff ( $TimeTicks )
    $TimeTicks = TimerInit ( )
    Local $_MinCalc = Int ( $_CountdownTime / ( 60 * 1000 ) ), $_SecCalc = $_CountdownTime - ( $_MinCalc * 60 * 1000 )
    $_SecCalc = Int ( $_SecCalc / 1000 )

    If $_MinCalc <= 0 And $_SecCalc <= 0 Then
        ;;steps through one second at a time
        Sleep ( 250 )
        ;;when it's done it removes the GUI and goes back to the entry interface
        GUIDelete ($_GuiCountDown)
        EnterTime()

    Else
        ;;changes colors of the GUI for the last 10 seconds
        If $_MinCalc <> $_Minutes Or $_SecCalc <> $_Seconds Then
            $_Minutes = $_MinCalc
            $_Seconds = $_SecCalc
            GUICtrlSetData ( $TimeLabel, StringFormat ( "%02u" & ":" & "%02u", $_Minutes, $_Seconds ) )
            If $_Minutes = 0 And $_Seconds <= 10 Then
                GUISetBkColor ( 0xA093FF, $_GuiCountDown )
            EndIf
        EndIf
    EndIf
EndFunc

Func PanelCountdown()
;;this part works fine, part of an external system I'm triggering via UDP sends
EndFunc

Func StopCountdown()
    MSGBox(4000,"DEBUG: Countdown Close","Countdown close button pressed")
    ;more UDP stuff that works fine
    GUIDelete($_GuiCountDown)
    ;;Back to the input interface
    EnterTime()
EndFunc

 

Link to comment
Share on other sites

It's some problem with swapping between OnEventmode On/Off I guess.

With swapping i couldn't make it work

But like this it does

;;Includes
#include <ButtonConstants.au3>
#include <EditConstants.au3>
#include <GUIConstantsEx.au3>
#include <GuiImageList.au3>
#include <GuiListView.au3>
#include <MsgBoxConstants.au3>
#include <StringConstants.au3>
#include <WinAPIFiles.au3>
#include <WindowsConstants.au3>

Global $SS_CENTER
Global $_CountdownTime
Global $_Minutes
Global $_Seconds
Global $TimeTicks
Global $TimeLabel
Global $_GuiCountDown
Global $EnterMinutes
Global $EnterSeconds
Global $StartButton
Global $Minutes
Global $Seconds
Global $_GuiEnterTime
Dim $aPanelCSV[0]

;Main function to trigger everything
Main()

Func Main()
    EnterTimeGUI()
    EnterTime()
EndFunc

Func PanelCount()
    ;stuff that works in the real script
EndFunc

;Primary function for entering in the countdown duration
Func EnterTimeGUI()
    ;;Create a GUI
    $_GuiEnterTime = GUICreate ( "Enter Start Time", 300, 150)
;~     Opt("GUIOnEventMode", 0)
    GUISetBkColor ( 0xFFFFFF )
    GUISetFont(10,0,0)
    $EnterLabel = GUICtrlCreateLabel ( "Minutes", 100,15,100,35)
    $EnterLabel = GUICtrlCreateLabel ( "Seconds", 160,15,100,35)
    GUISetFont(13.5,0,0)
    $EnterMinutes = GUICtrlCreateInput ("",105,35,45,35,$ES_NUMBER)
    $EnterSeconds = GUICtrlCreateInput ("",155,35,45,35,$ES_NUMBER)
    GUISetFont(12,0,0)
    $StartButton =     GUICtrlCreateButton    ("Start",110,80,80,50)
    GUISetState (@SW_SHOW,$_GuiEnterTime)
EndFunc

Func EnterTime()
    GUISetState (@SW_SHOW,$_GuiEnterTime)
;~     Opt("GUIOnEventMode", 0)
    While 1
;~      MsgBox ( 64,"","" )
        $MSG = GUIGetMsg()
        Select
            Case $MSG = $GUI_EVENT_CLOSE
                ;Exit
                MsgBox(4000,"DEBUG: Enter Time","enter time close button pressed")
            ;;Start button for countdown
            Case $MSG = $StartButton
                $Minutes = GUICtrlRead($EnterMinutes)
                $Seconds = GUICtrlRead($EnterSeconds)
                ;Math for the WallTime and local countdown functions
                 $Paneltime = (((60 * $Minutes) + $Seconds))
                 $_CountdownTime =(((60000 * $Minutes) + (1000 * $Seconds))+1000)
                Sleep(100)
                GUISetState (@SW_HIDE,$_GuiEnterTime)
                ;;Function starts the countdown timer on the WallTime panels
                PanelCountDown()
                ;;starts the function for local countdown
                CountDownGUI()
                ComputerCountDown()

        EndSelect
    WEnd
EndFunc

#cs
Local countdown--this was mostly taken from Wakillon's post in April of 2011, then modified for my use case. Full credit to Wakillon for this part.
https://www.autoitscript.com/forum/topic/127667-how-to-create-a-countdown-timer-in-autoit/
#ce

Func CountDownGUI()
;;Countdown GUI
    $_GuiCountDown = GUICreate ( "CountDown...", 500, 200, @DesktopWidth/2 -250, @DesktopHeight/2 -100)
    GUISwitch ($_GuiCountDown)
;~     Opt("GUIOnEventMode", 1)
;~     GUISetOnEvent($GUI_EVENT_CLOSE, "StopCountdown")
    GUISetBkColor ( 0xFFFFFF )
    $TimeLabel = GUICtrlCreateLabel ( "", 35, -10, 480, 180, $SS_CENTER )
    GUICtrlSetFont ( -1, 125, 800 )
    GUISetState (@SW_SHOW,$_GuiCountDown)
    ;WinSetOnTop ( $_GuiCountDown, "", 1 )
    $TimeTicks = TimerInit ( )
EndFunc

Func ComputerCountDown()
    Do
        ;;calls the function to begin the countdown
    $check = Check ( )
    If GUIGetMsg () = -3 Then StopCountdown()
    Until $check <> True
        EnterTime()

EndFunc

Func Check ( )
    $_CountdownTime -= TimerDiff ( $TimeTicks )
    $TimeTicks = TimerInit ( )
    Local $_MinCalc = Int ( $_CountdownTime / ( 60 * 1000 ) ), $_SecCalc = $_CountdownTime - ( $_MinCalc * 60 * 1000 )
    $_SecCalc = Int ( $_SecCalc / 1000 )

    If $_MinCalc <= 0 And $_SecCalc <= 0 Then
        ;;steps through one second at a time
        Sleep ( 250 )
        ;;when it's done it removes the GUI and goes back to the entry interface
        GUIDelete ($_GuiCountDown)
        Return False
    Else
        ;;changes colors of the GUI for the last 10 seconds
        If $_MinCalc <> $_Minutes Or $_SecCalc <> $_Seconds Then
            $_Minutes = $_MinCalc
            $_Seconds = $_SecCalc
            GUICtrlSetData ( $TimeLabel, StringFormat ( "%02u" & ":" & "%02u", $_Minutes, $_Seconds ) )
            If $_Minutes = 0 And $_Seconds <= 10 Then
                GUISetBkColor ( 0xA093FF, $_GuiCountDown )
            EndIf
        EndIf
    EndIf
    Return True
EndFunc

Func PanelCountdown()
;;this part works fine, part of an external system I'm triggering via UDP sends
EndFunc

Func StopCountdown()
    MSGBox(4000,"DEBUG: Countdown Close","Countdown close button pressed")
    ;more UDP stuff that works fine
;~  ExitLoop
    GUIDelete($_GuiCountDown)
    ;;Back to the input interface
    EnterTime()
EndFunc

 

why do i get garbage when i buy garbage bags? <_<

Link to comment
Share on other sites

Did you have a look at the wiki?
There you'll find a tutorial how to handle multiple GUIs: https://www.autoitscript.com/wiki/Managing_Multiple_GUIs

My UDFs and Tutorials:

Spoiler

UDFs:
Active Directory (NEW 2022-02-19 - Version 1.6.1.0) - Download - General Help & Support - Example Scripts - Wiki
ExcelChart (2017-07-21 - Version 0.4.0.1) - Download - General Help & Support - Example Scripts
OutlookEX (2021-11-16 - Version 1.7.0.0) - Download - General Help & Support - Example Scripts - Wiki
OutlookEX_GUI (2021-04-13 - Version 1.4.0.0) - Download
Outlook Tools (2019-07-22 - Version 0.6.0.0) - Download - General Help & Support - Wiki
PowerPoint (2021-08-31 - Version 1.5.0.0) - Download - General Help & Support - Example Scripts - Wiki
Task Scheduler (NEW 2022-07-28 - Version 1.6.0.1) - Download - General Help & Support - Wiki

Standard UDFs:
Excel - Example Scripts - Wiki
Word - Wiki

Tutorials:
ADO - Wiki
WebDriver - Wiki

 

Link to comment
Share on other sites

Hi all,

@Aelc 's solution works perfectly. 

@water--I was originally referencing the Wiki, which is how I landed on using the GUIOnEventMode switch--or, really hybrid mode, as I needed to use the case statements for the original button push then define the control (close) the second GUI with the GUISetOnEvent call.  With the original "While" loop I was unable to figure out a way to add a "case" for exiting the second GUI.  Lots of Googling/reading examples did NOT lead to the "Do...Until" statement that was suggested (and with which, until now, I was unfamiliar).

That said, I understand the changes you made/suggested (determine the control ID, use a Do...Until statement in place of the While, use the Control ID to determine which GUI is being closed), and am already re-thinking a few previous scripts where I may go back and make some modifications for similar issues where I found less...elegant solutions.

Sorry the code is confusing.  I'm green enough that I'm probably not as organized (or pre-planned) as I should/could be for much of my coding.  "On the fly" planning (and troubleshooting) can definitely lead to things being a bit sloppy.

That said, THANK YOU again--learning new things every day!

Link to comment
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
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...