Jump to content

Problem with multiple GUI windows


Recommended Posts

I hope i've placed this in the right forum. My issue is with a script in general, though the script happens to have GUI windows.

By default all the windows in my script act normally, but notice that while the progress bar is moving if you try to close the window (Clicking the "x") it will continue along its business and then the whole program dies after its done. My guess is that its because the close window button is passed to the other "GUIGetMsg" functions. how do i prevent this from happening so that the program just goes back to window 2 like its supposed to? Dont want the user causing any issues ;)

#include <GUIConstantsEx.au3>

Global $win_1, $win_2, $win_3

$win_1 = GUICreate("Window 1",400,400)
$button_1 = GUICtrlCreateButton("Open",10,10,100,50)

GUISetState()

While 1
    $msg = GUIGetMsg(1)
    
    Select
    Case $msg[0] = $button_1
        newWindow()
    Case $msg[0] = $GUI_EVENT_CLOSE
        Exit
    EndSelect
    
WEnd

Func newWindow()
    
    $win_2 = GUICreate("Window 2",300,200,-1,-1,-1,-1,$win_1)
    $button_2 = GUICtrlCreateButton("Start",10,10,100,50)
    
    GUISetState(@SW_DISABLE,$win_1)
    GUISetState(@SW_SHOW,$win_2)
    
    While 1
        $msg = GUIGetMsg(1)
        
        Select
        Case $msg[0] = $button_2
            startStuff()
        Case $msg[0] = $GUI_EVENT_CLOSE
            GUISetState(@SW_ENABLE, $win_1)
            GUIDelete($win_2)
            ExitLoop(1)
        EndSelect
        
    WEnd
EndFunc

Func startStuff()
    
    $win_3 = GUICreate("Doing something...",200,100,-1,-1,-1,-1,$win_2)
    $prog = GUICtrlCreateProgress(10,40,180,20)
    
    GUISetState(@SW_DISABLE,$win_2)
    GUISetState(@SW_SHOW,$win_3)
    
    For $i = 1 To 20
        Sleep(1000)
        GUICtrlSetData($prog, $i * 100 / 20)
    Next
    
    Sleep(3000)
    GUISetState(@SW_ENABLE, $win_2)
    GUIDelete($win_3)
    
EndFunc
Link to comment
Share on other sites

I hope i've placed this in the right forum. My issue is with a script in general, though the script happens to have GUI windows.

By default all the windows in my script act normally, but notice that while the progress bar is moving if you try to close the window (Clicking the "x") it will continue along its business and then the whole program dies after its done. My guess is that its because the close window button is passed to the other "GUIGetMsg" functions. how do i prevent this from happening so that the program just goes back to window 2 like its supposed to? Dont want the user causing any issues ;)

#include <GUIConstantsEx.au3>

Global $win_1, $win_2, $win_3

$win_1 = GUICreate("Window 1",400,400)
$button_1 = GUICtrlCreateButton("Open",10,10,100,50)

GUISetState()

While 1
    $msg = GUIGetMsg(1)
    
    Select
    Case $msg[0] = $button_1
        newWindow()
    Case $msg[0] = $GUI_EVENT_CLOSE
        Exit
    EndSelect
    
WEnd

Func newWindow()
    
    $win_2 = GUICreate("Window 2",300,200,-1,-1,-1,-1,$win_1)
    $button_2 = GUICtrlCreateButton("Start",10,10,100,50)
    
    GUISetState(@SW_DISABLE,$win_1)
    GUISetState(@SW_SHOW,$win_2)
    
    While 1
        $msg = GUIGetMsg(1)
        
        Select
        Case $msg[0] = $button_2
            startStuff()
        Case $msg[0] = $GUI_EVENT_CLOSE
            GUISetState(@SW_ENABLE, $win_1)
            GUIDelete($win_2)
            ExitLoop(1)
        EndSelect
        
    WEnd
EndFunc

Func startStuff()
    
    $win_3 = GUICreate("Doing something...",200,100,-1,-1,-1,-1,$win_2)
    $prog = GUICtrlCreateProgress(10,40,180,20)
    
    GUISetState(@SW_DISABLE,$win_2)
    GUISetState(@SW_SHOW,$win_3)
    
    For $i = 1 To 20
        Sleep(1000)
        GUICtrlSetData($prog, $i * 100 / 20)
    Next
    
    Sleep(3000)
    GUISetState(@SW_ENABLE, $win_2)
    GUIDelete($win_3)
    
EndFunc

while you're in your loop populating the progress bar, your loop that is checking for messages is stopped. msg is not re-evaluated until after your progress bar is complete. as far as why your exiting on the second window exits your script, from the help file:

when a new window is created it becomes the "default" window for future GUI operations (including control creation).

In the GUI Reference part of the help file read the onevent mode topic and it will tell you how to fix that
Link to comment
Share on other sites

If the user bangs on the exit button while you're doing stuff, the msg queue can stack up enough $GUI_EVENT_CLOSE characters to back you all the way out of your program. After your StartStuff() call you can add these 2 lines to clear out anything left in the queue when control returns from the function:

While GUIGetMsg() ; clear anything in msg queue
WEnd

Edit: You'd need to add an "If GuiGetMsg() = $GUI_EVENT_CLOSE Then..." test in your startstuff() loop to be able to bust out of that function prematurely.

Is this better behavior?

#include <GUIConstantsEx.au3>

Global $win_1, $win_2, $win_3

$win_1 = GUICreate("Window 1",400,400)
$button_1 = GUICtrlCreateButton("Open",10,10,100,50)

GUISetState()

While 1
    $msg = GUIGetMsg(1)

    Select
    Case $msg[0] = $button_1
        newWindow()
    Case $msg[0] = $GUI_EVENT_CLOSE
        Exit
    EndSelect

WEnd

Func newWindow()

    $win_2 = GUICreate("Window 2",300,200,-1,-1,-1,-1,$win_1)
    $button_2 = GUICtrlCreateButton("Start",10,10,100,50)

    GUISetState(@SW_DISABLE,$win_1)
    GUISetState(@SW_SHOW,$win_2)

    While 1
        $msg = GUIGetMsg(1)

        Select
        Case $msg[0] = $button_2
            startStuff()
            While GUIGetMsg() ; clear anything in msg queue
            WEnd
        Case $msg[0] = $GUI_EVENT_CLOSE
            GUISetState(@SW_ENABLE, $win_1)
            GUIDelete($win_2)
            ExitLoop(1)
        EndSelect

    WEnd
EndFunc

Func startStuff()

    $win_3 = GUICreate("Doing something...",200,100,-1,-1,-1,-1,$win_2)
    $prog = GUICtrlCreateProgress(10,40,180,20)

    GUISetState(@SW_DISABLE,$win_2)
    GUISetState(@SW_SHOW,$win_3)

    For $i = 1 To 20
        Sleep(100)
        If GUIGetMsg() = $GUI_EVENT_CLOSE Then ExitLoop
        GUICtrlSetData($prog, $i * 100 / 20)
        If GUIGetMsg() = $GUI_EVENT_CLOSE Then ExitLoop
    Next

    Sleep(100)
    GUISetState(@SW_ENABLE, $win_2)
    GUIDelete($win_3)

EndFunc
Edited by Spiff59
Link to comment
Share on other sites

Anything a user clicks on in a GUI is stacked up in a queue, if that GUI doesn't have a GUIGetMsg() statement to process (and delete from) that queue, then anything placed in there is still present and will be serviced by other GUIGetMsg() statements elsewhere in your script. You just needed to empty the queue so that leftover clicks from the third GUI are not still waiting in the queue to be processed by other GUI's.

On a side note, it appears updating a progressbar is resource intensive, as in the example I modified, it took two checks for $GUI_EVENT_CLOSE (one after the sleep(), and another after the GUISetData() statement) to make the exit from the progress bar responsive.

Edit: You could also modify the style of the thrid GUI to where it doesn't even have the minimize/maximize/exit buttons.

Edited by Spiff59
Link to comment
Share on other sites

i thought of removing the minimize, maximize, and close buttons, but i see nowhere in common styles or extended styles that would do this. This would be the ideal situation because in my real status bar i expect no user input whatsoever.

Link to comment
Share on other sites

You'll have to add: #include <WindowsConstants.au3>

But neither the $WS_BORDER, $WS_POPUP, or $WS_POPUPWINDOW styles (of the GUICreate() statement) have the buttons. They all have a slightly different appearance.

Edited by Spiff59
Link to comment
Share on other sites

ahhh, i fail.... lol thanks! seems like theres something goofy with the window size now, but im guessing its counting the title bar as part of the window height, i will make the needed changes.

Problem solved, thanks alot!

Link to comment
Share on other sites

Your script needs just a slight modification:

#include <GUIConstantsEx.au3>

Global $win_1, $win_2, $win_3

$win_1 = GUICreate("Window 1",400,400)
$button_1 = GUICtrlCreateButton("Open",10,10,100,50)

GUISetState()

While 1
    $msg = GUIGetMsg(1)
    
    Select
    Case $msg[0] = $button_1
        newWindow()
    Case $msg[0] = $GUI_EVENT_CLOSE
        Exit
    EndSelect
    
WEnd

Func newWindow()
    
    $win_2 = GUICreate("Window 2",300,200,-1,-1,-1,-1,$win_1)
    $button_2 = GUICtrlCreateButton("Start",10,10,100,50)
    
    GUISetState(@SW_DISABLE,$win_1)
    GUISetState(@SW_SHOW,$win_2)
    GUISwitch($win_2)
    
    While 1
        $msg = GUIGetMsg(1)
        
        Select
        Case $msg[0] = $button_2
            startStuff()
        Case $msg[0] = $GUI_EVENT_CLOSE
            ExitLoop(1)
        EndSelect
        
    WEnd
    GUISetState(@SW_ENABLE, $win_1)
    GUIDelete($win_2)
    GUISwitch($win_1)
EndFunc

Func startStuff()
    
    $win_3 = GUICreate("Doing something...",200,100,-1,-1,-1,-1,$win_2)
    $prog = GUICtrlCreateProgress(10,40,180,20)
    
    GUISetState(@SW_DISABLE,$win_2)
    GUISetState(@SW_SHOW,$win_3)
    GUISwitch($win_3)
    
    Local $t = TimerInit()
    Local $td = 0
    Do
        If $GUI_EVENT_CLOSE = GUIGetMsg() Then ExitLoop
        $td = TimerDiff($t)
        GUICtrlSetData($prog, $td / 200)
    Until $td > 20000
    
    GUISetState(@SW_ENABLE, $win_2)
    GUIDelete($win_3)
    GUISwitch($win_2)
EndFunc

Notice the GUISwitch() calls before the start and after the end of the GetMsg loops and $GUI_EVENT_CLOSE = GUIGetMsg() query inside of the worker loop (I also removed Sleep() call there to avoid GUI unresponsiveness).

UDFS & Apps:

Spoiler

DDEML.au3 - DDE Client + Server
Localization.au3 - localize your scripts
TLI.au3 - type information on COM objects (TLBINF emulation)
TLBAutoEnum.au3 - auto-import of COM constants (enums)
AU3Automation - export AU3 scripts via COM interfaces
TypeLibInspector - OleView was yesterday

Coder's last words before final release: WE APOLOGIZE FOR INCONVENIENCEĀ 

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...