Jump to content

GUIs launched from GUIs [solved]


icu
 Share

Recommended Posts

Dear AutoIt Community,

I would like help pointing the way to a solution.

I've got a GUI, lets call it '$Form_Main' and I want it to launch a settings GUI, lets call it '$Form_Settings'.

I've made both $Form_Main and $Form_Settings in Koda and both lots of code are in MessageLoop Mode.

What I can't figure out is how to launch $Form_Settings from inside $Form_Main (with a button) and how I would then handle passing variable changes in $Form_Settings back to $Form_Main and how to handle $GUI_EVENT_CLOSE in $Form_Settings without closing $Form_Main.

I have tried to use the Wiki article on managing multiple GUIs as a guide but I don't see how I can apply it's sample code. The example shows two GUIs opening up simultaneously, whereas I want $Form_Main always running and $Form_Settings to only start once I click a button and only close itself if $GUI_EVENT_CLOSE is triggered.

Please don't ask for code, I've got several hundred lines ;-) If possible I need a conceptual answer (I'm happy to do the homework if pointed in the right direction) otherwise example code would be greatly appreciated.

Many thanks for any and all help!

-icu

Edited by icu
Link to comment
Share on other sites

  • Moderators

icu,

The example shows two GUIs opening up simultaneously

No it does not! :)

I wrote the tutorial and the proposed solution shows the second GUI opening when a button on the first is pressed. If you want to prevent the first GUI from reacting when the second GUI is present, you need to disable/enable it like this (look for <<<<<<<< as usual):

#include <GUIConstantsEx.au3>

Global $hGUI2 = 9999, $hButton3 = 9999 ; Predeclare the variables with dummy values to prevent firing the Case statements

gui1()

Func gui1()

    $hGUI1 = GUICreate("Gui 1", 200, 200, 100, 100)
    $hButton1 = GUICtrlCreateButton("Msgbox 1", 10, 10, 80, 30)
    $hButton2 = GUICtrlCreateButton("Show Gui 2", 10, 60, 80, 30)
    GUISetState()

    While 1
        $aMsg = GUIGetMsg(1) ; Use advanced parameter to get array
        Switch $aMsg[1] ; check which GUI sent the message
            Case $hGUI1
                Switch $aMsg[0] ; Now check for the messages for $hGUI1
                    Case $GUI_EVENT_CLOSE ; If we get the CLOSE message from this GUI - we exit <<<<<<<<<<<<<<<
                        ExitLoop
                    Case $hButton1
                        MsgBox("", "MsgBox 1", "Test from Gui 1")
                    Case $hButton2
                        GUICtrlSetState($hButton2, $GUI_DISABLE)
                        WinSetState($hGUI1, "", @SW_DISABLE) ; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
                        gui2()
                EndSwitch
            Case $hGUI2
                Switch $aMsg[0] ; Now check for the messages for $hGUI2
                    Case $GUI_EVENT_CLOSE ; If we get the CLOSE message from this GUI - we just delete the GUI <<<<<<<<<<<<<<<
                        WinSetState($hGUI1, "", @SW_ENABLE) ; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
                        GUIDelete($hGUI2)
                        GUICtrlSetState($hButton2, $GUI_ENABLE)
                    Case $hButton3
                        MsgBox("", "MsgBox", "Test from Gui 2")
                EndSwitch
        EndSwitch
    WEnd

EndFunc   ;==>gui1

Func gui2()

    $hGUI2 = GUICreate("Gui 2", 200, 200, 350, 350)
    $hButton3 = GUICtrlCreateButton("MsgBox 2", 10, 10, 80, 30)
    GUISetState()

EndFunc   ;==>gui2

All clear? ;)

M23

Public_Domain.png.2d871819fcb9957cf44f4514551a2935.png Any of my own code posted anywhere on the forum is available for use by others without any restriction of any kind

Open spoiler to see 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

 

Link to comment
Share on other sites

@Melba23: Whoops! Thanks for the quick reply and for the correction. My mistake! :)

A couple of things I don't quite understand...

Q1: Why did you put the main GUI into a function with a loop and put the sub-GUI into another function without one?

Q2: Why should I copy this idea? I.e. Predeclare some dummy GUI variables, create a function for Form_Main with a loop inside it and create another function for Form_Settings? Is there something I'm not seeing here because it seems extreme to me to encapsulate each GUI into a function. Why can't there be two GUIs defined outside of a loop and a loop with a switch and a trigger to start the sub-GUI?

Many thanks,

-icu

Edited by icu
Link to comment
Share on other sites

  • Moderators

icu,

Q1: Why did you put the main GUI into a function with a loop and put the sub-GUI into another function without one?

Because if you use the "advanced" parameter with GUIGetMsg you only need one loop. :)

You could very well have 2 loops, one for each GUI, but you would still have the problem of distinguishing which GUI sent the $GUI_EVENT_CLOSE message unless you disable the main while the child is active or use the "advanced" parameter - which rahter defeats the .

Q2: Why should I copy this idea?

You do not have to. There are many ways of coding a main GUI and a child - I just used this method for the tutorial to demonstrate how you can use the "advanced" parameter with GUIGetMsg. You can write your code as you wish - I will not get annoyed, promise! ;)

M23

Public_Domain.png.2d871819fcb9957cf44f4514551a2935.png Any of my own code posted anywhere on the forum is available for use by others without any restriction of any kind

Open spoiler to see 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

 

Link to comment
Share on other sites

@Melba23: Thanks again for your easy to understand explanations. I've followed the structure of your code, i.e. predeclare some dummy variables, put the main GUI into a function with a loop and put the sub-GUI into another function without one and it works... but then you knew that would happen :-)

So this handles the 'Click here in the Main GUI and a new child GUI pops up' problem and the 'Click close on the child GUI and the Main GUI doesn't close' problem.

However I'm having trouble thinking of a way to simply pass variables and variable changes from the child GUI back to the main GUI because the GUIs are encapsulated within functions and as far as I can gather, the variables only exist within each separate function and not the whole program. Declaring Global variables with a function won't work (and I don't know why... I thought if you declare something Global no matter where it would be Global everywhere).

My only idea at this point is to pre-declare a large set of 'buffer' Global variables outside of the GUI functions to capture any changes to the matching variables in the child GUI so the main GUI can 'read' them. I imagine this is going to be messy and I was hoping you could point the way to an easier solution?

Kind regards,

-icu

Link to comment
Share on other sites

I've given up on the idea to pre-declare a large set of 'buffer' Global variables to maintain all the MessageLoop code I've written.

I just can't seem to figure it out and it's getting too complicated to conceptualise all of the changes I need to make to my existing code.

So I went back to the drawing board and re-thought about using OnEvent code (having never used it).

I played with Koda (thankfully I saved all those .kxf files) until it spat out OnEvent code for my two GUIs and it seems like this is the best solution for having variables interact and be changed between a main and child GUI. So while it pains me to re-write everything in OnEvent mode, it seems like a more modular and robust solution if I want to add more child GUIs to my program.

If you are going to code a 'settings' child GUI I think you should choose OnEvent code as the way to go.

Edited by icu
Link to comment
Share on other sites

  • Moderators

icu,

I'm having trouble thinking of a way to simply pass variables and variable changes from the child GUI back to the main GUI because the GUIs are encapsulated within functions and as far as I can gather, the variables only exist within each separate function and not the whole program

But you can pass variables as parameters to and from functions in MessageLoop mode - that is what parameters are for. ;)

If you are going to code a 'settings' child GUI I think you should choose [OnEvent mode] as the way to go.

Not at all, you can easily use either mode for this - I have a script with many dialogs, many of which change settings in the main script. There are advantages and disadvantages to both modes - you need to choose the one that best suits the situation. :)

And if you are worried about the number of variables you need to pass - just remember that you can pass arrays as parameters! :D

Good luck with your script - whichever mode you choose. ;)

M23

Public_Domain.png.2d871819fcb9957cf44f4514551a2935.png Any of my own code posted anywhere on the forum is available for use by others without any restriction of any kind

Open spoiler to see 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

 

Link to comment
Share on other sites

@Melba23: Thanks again for your reply:

But you can pass variables as parameters to and from functions in MessageLoop mode - that is what parameters are for.

I have no idea how to do this and I haven't found any resources to learn from or adapt for my purpose. Any ideas?

Not at all, you can easily use either mode for this

I would debate the use of the word "easily"... perhaps for a 'Code God' like yourself ;-) I'm a mere mortal without previous coding experience trying to make sense of it all. I certainly feel I've come a long way thanks to the efforts of the AutoIt community putting together an excellent help file, how-to resources, and the forum. I've stuck to AutoIt because solutions always seemed obvious or when I got stuck and asked for help the solutions suggested by others seemed obvious in hindsight. This has not been my experience for getting MessageLoop mode working with a main and child GUI. When you are self taught you are always caught in the trap of not knowing what you don't know.

In my frustration I turned to experimenting with OnEvent mode and it was instantly understandable... no more $GUI_EVENT_CLOSE problem and each input for either GUI (i.e. a button) is a function that can easily manipulate and interact with any other function or variable in the rest of the program.

I'm still clueless how it would work with MessageLoop mode (and not for lack of trying)... and that's my point really. If it was so easy to use MessageLoop mode I would have got it by now!

-icu

Edited by icu
Link to comment
Share on other sites

  • Moderators

icu,

pass variables as parameters to and from functions in MessageLoop mode

A very simple example: ;)

; Declare our values
$iVar_1 = 2
$iVar_2 = 3

; Pass the 2 variables as parameters to the function and get a value in return
$iResult = _Multiply($iVar_1, $iVar_2)

; Display the result
MsgBox(0, "Result", $iVar_1 & " x " & $iVar_2 & " = " & $iResult)

; The function takes 2 parameters as input
Func _Multiply($x, $y)

    ; These parameters take the value of the variables passed to the function
    MsgBox(0, "In the function", "$x = " & $x & @CRLF & "$y = " & $y)

    ; And you can return a value directly - here is is the value of the product of the parameters
    Return $x * $y

EndFunc

As to not understanding MessageLoop mode - do not worry, it will come to you in the end. As I said earlier, there is not hard and fast rule as to which mode to use - I tend to use MessageLoop most the time as I prefer it, others here use OnEvent almost exclusively. You just pick the one which best suits you for the task you are coding. But do try and get yuur head around MessageLoop mode - without it you are missing a valuable tool in your coding toolbox. :D

As a help to your education, here is a short script in MessageLoop mode with a child settings dialog - see if you can follow it: :)

#include <GUIConstantsEx.au3>

_Main()

Func _Main()

    Local $hGUI = GUICreate("Test", 500, 500)

    Local $hLabel_1 = GUICtrlCreateLabel("Label 1", 10,  10, 200, 70)
    GUICtrlSetBkColor(-1, 0xFF8080)
    Local $hLabel_2 = GUICtrlCreateLabel("Label 2", 10, 100, 200, 70)
    GUICtrlSetBkColor(-1, 0xFF8080)
    Local $hLabel_3 = GUICtrlCreateLabel("Label 3", 10, 190, 200, 70)
    GUICtrlSetBkColor(-1, 0xFF8080)
    Local $hLabel_4 = GUICtrlCreateLabel("Label 4", 10, 280, 200, 70)
    GUICtrlSetBkColor(-1, 0xFF8080)
    Local $hLabel_5 = GUICtrlCreateLabel("Label 5", 10, 370, 200, 70)
    GUICtrlSetBkColor(-1, 0xFF8080)

    Local $hButton_Settings = GUICtrlCreateButton("Settings", 400, 10, 80, 30)

    GUISetState()

    While 1

        $iMsg = GUIGetMsg()

        If $iMsg <> 0 Then ConsoleWrite($iMsg & @CRLF)

        Switch $iMsg
            Case $GUI_EVENT_CLOSE
                Exit
            Case $hButton_Settings
                ; We pass the Local variables to another function
                _Settings($hGUI, $hLabel_1, $hLabel_2, $hLabel_3, $hLabel_4, $hLabel_5)
        EndSwitch

    WEnd

EndFunc

Func _Settings($hWnd, $h1, $h2, $h3, $h4, $h5)
    
    ; This function can now use these parameters as Local variables

    GUISetState(@SW_DISABLE, $hWnd)

    Local $hGUI_Settings = GUICreate("Settings", 300, 300)

    ; I would actually use a loop and an array here, but I have kept it simple for this demo
    GUIStartGroup()
    GUICtrlCreateLabel("Label 1 Colour", 10, 10, 200, 20)
    Local $hRadio_1_Red = GUICtrlCreateRadio(" Red", 10, 30, 100, 20)
    GUICtrlSetState(-1, $GUI_CHECKED)
    GUICtrlCreateRadio(" Green", 110, 30, 100, 20)
    GUIStartGroup() ; make each pair of radios a separater group so that you can only select one colour for each label
    GUICtrlCreateLabel("Label 2 Colour", 10, 60, 200, 20)
    Local $hRadio_2_Red = GUICtrlCreateRadio(" Red", 10, 80, 100, 20)
    GUICtrlSetState(-1, $GUI_CHECKED)
    GUICtrlCreateRadio(" Green", 110, 80, 100, 20)
    GUIStartGroup()
    GUICtrlCreateLabel("Label 3 Colour", 10, 110, 200, 20)
    Local $hRadio_3_Red = GUICtrlCreateRadio(" Red", 10, 130, 100, 20)
    GUICtrlSetState(-1, $GUI_CHECKED)
    GUICtrlCreateRadio(" Green", 110, 130, 100, 20)
    GUIStartGroup()
    GUICtrlCreateLabel("Label 4 Colour", 10, 160, 200, 20)
    Local $hRadio_4_Red = GUICtrlCreateRadio(" Red", 10, 180, 100, 20)
    GUICtrlSetState(-1, $GUI_CHECKED)
    GUICtrlCreateRadio(" Green", 110, 180, 100, 20)
    GUIStartGroup()
    GUICtrlCreateLabel("Label 5 Colour", 10, 210, 200, 20)
    Local $hRadio_5_Red = GUICtrlCreateRadio(" Red", 10, 230, 100, 20)
    GUICtrlSetState(-1, $GUI_CHECKED)
    GUICtrlCreateRadio(" Green", 110, 230, 100, 20)

    Local $hButton_Apply = GUICtrlCreateButton("Apply", 10, 260, 80, 30)

    GUISetState()

    While 1

        Switch GUIGetMsg()
            Case $hButton_Apply
                ; Check which radios are set - gain a loop and array woudl be better but this is a demo
                If GUICtrlRead($hRadio_1_Red) = 1 Then
                    GUICtrlSetBkColor($h1, 0xFF8080)
                Else
                    GUICtrlSetBkColor($h1, 0x80FF80)
                EndIf
                If GUICtrlRead($hRadio_2_Red) = 1 Then
                    GUICtrlSetBkColor($h2, 0xFF8080)
                Else
                    GUICtrlSetBkColor($h2, 0x80FF80)
                EndIf
                If GUICtrlRead($hRadio_3_Red) = 1 Then
                    GUICtrlSetBkColor($h3, 0xFF8080)
                Else
                    GUICtrlSetBkColor($h3, 0x80FF80)
                EndIf
                If GUICtrlRead($hRadio_4_Red) = 1 Then
                    GUICtrlSetBkColor($h4, 0xFF8080)
                Else
                    GUICtrlSetBkColor($h4, 0x80FF80)
                EndIf
                If GUICtrlRead($hRadio_5_Red) = 1 Then
                    GUICtrlSetBkColor($h5, 0xFF8080)
                Else
                    GUICtrlSetBkColor($h5, 0x80FF80)
                EndIf
                ; And then exit using the same code as the real exit
                ContinueCase
            Case $GUI_EVENT_CLOSE
                ; Important to reenable the main GUI before deleting the child
                GUISetState(@SW_ENABLE, $hWnd)
                GUIDelete($hGUI_Settings)
                ExitLoop
        EndSwitch

    WEnd

    ; Not really necessary as the function returns automatically as the code ends
    Return

EndFunc

And not a Global variable in sight! :D

Please ask if you have any questions - after all, the idea is that you understand! ;)

M23

Public_Domain.png.2d871819fcb9957cf44f4514551a2935.png Any of my own code posted anywhere on the forum is available for use by others without any restriction of any kind

Open spoiler to see 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

 

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