Difference between revisions of "Managing Multiple GUIs"

From AutoIt Wiki
Jump to navigation Jump to search
m (MessageLoop Mode)
m (variable renameing: $hButton >> $idButton)
Line 7: Line 7:
 
<syntaxhighlight lang="autoit"> #include <GUIConstantsEx.au3>
 
<syntaxhighlight lang="autoit"> #include <GUIConstantsEx.au3>
 
   
 
   
  Global $hButton3 = 9999
+
  Global $idButton3 = 9999
 
   
 
   
 
  gui1()
 
  gui1()
Line 13: Line 13:
 
  Func gui1()
 
  Func gui1()
 
     $hGUI1 = GUICreate("Gui 1", 200, 200, 100, 100)
 
     $hGUI1 = GUICreate("Gui 1", 200, 200, 100, 100)
     $hButton1 = GUICtrlCreateButton("Msgbox 1", 10, 10, 80, 30)
+
     $idButton1 = GUICtrlCreateButton("Msgbox 1", 10, 10, 80, 30)
     $hButton2 = GUICtrlCreateButton("Show Gui 2", 10, 60, 80, 30)
+
     $idButton2 = GUICtrlCreateButton("Show Gui 2", 10, 60, 80, 30)
 
     GUISetState()
 
     GUISetState()
 
   
 
   
Line 21: Line 21:
 
             Case $GUI_EVENT_CLOSE
 
             Case $GUI_EVENT_CLOSE
 
                 ExitLoop
 
                 ExitLoop
             Case $hButton1
+
             Case $idButton1
 
                 MsgBox("", "MsgBox 1", "Test from Gui 1")
 
                 MsgBox("", "MsgBox 1", "Test from Gui 1")
             Case $hButton2
+
             Case $idButton2
                 GUICtrlSetState($hButton2, $GUI_DISABLE)
+
                 GUICtrlSetState($idButton2, $GUI_DISABLE)
 
                 gui2()
 
                 gui2()
             Case $hButton3
+
             Case $idButton3
 
                 MsgBox("", "MsgBox 2", "Test from Gui 2")  
 
                 MsgBox("", "MsgBox 2", "Test from Gui 2")  
 
         EndSwitch
 
         EndSwitch
Line 34: Line 34:
 
  Func gui2()
 
  Func gui2()
 
     $hGUI2 = GUICreate("Gui 2", 200, 200, 350, 350)
 
     $hGUI2 = GUICreate("Gui 2", 200, 200, 350, 350)
     $hButton3 = GUICtrlCreateButton("MsgBox 2", 10, 10, 80, 30)
+
     $idButton3 = GUICtrlCreateButton("MsgBox 2", 10, 10, 80, 30)
 
     GUISetState()
 
     GUISetState()
 
  EndFunc  ;==>gui2 </syntaxhighlight>
 
  EndFunc  ;==>gui2 </syntaxhighlight>
Line 46: Line 46:
 
  Func gui1()
 
  Func gui1()
 
     $hGUI1 = GUICreate("Gui 1", 200, 200, 100, 100)
 
     $hGUI1 = GUICreate("Gui 1", 200, 200, 100, 100)
     $hButton1 = GUICtrlCreateButton("Msgbox 1", 10, 10, 80, 30)
+
     $idButton1 = GUICtrlCreateButton("Msgbox 1", 10, 10, 80, 30)
     $hButton2 = GUICtrlCreateButton("Show Gui 2", 10, 60, 80, 30)
+
     $idButton2 = GUICtrlCreateButton("Show Gui 2", 10, 60, 80, 30)
 
     GUISetState()
 
     GUISetState()
 
   
 
   
Line 54: Line 54:
 
             Case $GUI_EVENT_CLOSE
 
             Case $GUI_EVENT_CLOSE
 
                 ExitLoop
 
                 ExitLoop
             Case $hButton1
+
             Case $idButton1
 
                 MsgBox("", "MsgBox 1", "Test from Gui 1")
 
                 MsgBox("", "MsgBox 1", "Test from Gui 1")
             Case $hButton2
+
             Case $idButton2
 
                 ; Disable the first GUI
 
                 ; Disable the first GUI
 
                 GUISetState(@SW_DISABLE, $hGUI1)
 
                 GUISetState(@SW_DISABLE, $hGUI1)
Line 68: Line 68:
 
  Func gui2()
 
  Func gui2()
 
     $hGUI2 = GUICreate("Gui 2", 200, 200, 350, 350)
 
     $hGUI2 = GUICreate("Gui 2", 200, 200, 350, 350)
     $hButton3 = GUICtrlCreateButton("MsgBox 2", 10, 10, 80, 30)
+
     $idButton3 = GUICtrlCreateButton("MsgBox 2", 10, 10, 80, 30)
 
     GUISetState()
 
     GUISetState()
 
   
 
   
Line 77: Line 77:
 
                 GUIDelete($hGUI2)
 
                 GUIDelete($hGUI2)
 
                 ExitLoop
 
                 ExitLoop
             Case $hButton3
+
             Case $idButton3
 
                 MsgBox("", "MsgBox 2", "Test from Gui 2")
 
                 MsgBox("", "MsgBox 2", "Test from Gui 2")
 
  EndSwitch
 
  EndSwitch
Line 88: Line 88:
 
     Case $GUI_EVENT_CLOSE
 
     Case $GUI_EVENT_CLOSE
 
         ; Code
 
         ; Code
     Case $hButton1
+
     Case $idButton1
 
         ; Code
 
         ; Code
 
  EndSwitch </syntaxhighlight>  
 
  EndSwitch </syntaxhighlight>  
Line 106: Line 106:
 
             Case $GUI_EVENT_CLOSE
 
             Case $GUI_EVENT_CLOSE
 
                 ; Code
 
                 ; Code
             Case $hButton3
+
             Case $idButton3
 
                 ; Code
 
                 ; Code
 
         EndSwitch
 
         EndSwitch
Line 115: Line 115:
 
<syntaxhighlight lang="autoit"> #include <GUIConstantsEx.au3>
 
<syntaxhighlight lang="autoit"> #include <GUIConstantsEx.au3>
 
   
 
   
  Global $hGUI2 = 9999, $hButton3 ; Predeclare the variables with dummy values to prevent firing the Case statements, only for GUI this time
+
  Global $hGUI2 = 9999, $idButton3 ; Predeclare the variables with dummy values to prevent firing the Case statements, only for GUI this time
 
   
 
   
 
  gui1()
 
  gui1()
Line 121: Line 121:
 
  Func gui1()
 
  Func gui1()
 
     $hGUI1 = GUICreate("Gui 1", 200, 200, 100, 100)
 
     $hGUI1 = GUICreate("Gui 1", 200, 200, 100, 100)
     $hButton1 = GUICtrlCreateButton("Msgbox 1", 10, 10, 80, 30)
+
     $idButton1 = GUICtrlCreateButton("Msgbox 1", 10, 10, 80, 30)
     $hButton2 = GUICtrlCreateButton("Show Gui 2", 10, 60, 80, 30)
+
     $idButton2 = GUICtrlCreateButton("Show Gui 2", 10, 60, 80, 30)
 
     GUISetState()
 
     GUISetState()
 
   
 
   
Line 132: Line 132:
 
                     Case $GUI_EVENT_CLOSE ; If we get the CLOSE message from this GUI - we exit <<<<<<<<<<<<<<<
 
                     Case $GUI_EVENT_CLOSE ; If we get the CLOSE message from this GUI - we exit <<<<<<<<<<<<<<<
 
                         ExitLoop
 
                         ExitLoop
                     Case $hButton1
+
                     Case $idButton1
 
                         MsgBox("", "MsgBox 1", "Test from Gui 1")
 
                         MsgBox("", "MsgBox 1", "Test from Gui 1")
                     Case $hButton2
+
                     Case $idButton2
                         GUICtrlSetState($hButton2, $GUI_DISABLE)
+
                         GUICtrlSetState($idButton2, $GUI_DISABLE)
 
                         gui2()
 
                         gui2()
 
                 EndSwitch
 
                 EndSwitch
Line 142: Line 142:
 
                     Case $GUI_EVENT_CLOSE ; If we get the CLOSE message from this GUI - we just delete the GUI <<<<<<<<<<<<<<<
 
                     Case $GUI_EVENT_CLOSE ; If we get the CLOSE message from this GUI - we just delete the GUI <<<<<<<<<<<<<<<
 
                         GUIDelete($hGUI2)
 
                         GUIDelete($hGUI2)
                         GUICtrlSetState($hButton2, $GUI_ENABLE)
+
                         GUICtrlSetState($idButton2, $GUI_ENABLE)
                     Case $hButton3
+
                     Case $idButton3
 
                         MsgBox("", "MsgBox", "Test from Gui 2")
 
                         MsgBox("", "MsgBox", "Test from Gui 2")
 
                 EndSwitch
 
                 EndSwitch
Line 152: Line 152:
 
  Func gui2()
 
  Func gui2()
 
     $hGUI2 = GUICreate("Gui 2", 200, 200, 350, 350)
 
     $hGUI2 = GUICreate("Gui 2", 200, 200, 350, 350)
     $hButton3 = GUICtrlCreateButton("MsgBox 2", 10, 10, 80, 30)
+
     $idButton3 = GUICtrlCreateButton("MsgBox 2", 10, 10, 80, 30)
 
     GUISetState()
 
     GUISetState()
 
  EndFunc  ;==>gui2 </syntaxhighlight>
 
  EndFunc  ;==>gui2 </syntaxhighlight>
Line 164: Line 164:
 
  Opt("GUIOnEventMode", 1)
 
  Opt("GUIOnEventMode", 1)
 
   
 
   
  Global $hGUI2, $hButton2 ; Predeclare these variables
+
  Global $hGUI2, $idButton2 ; Predeclare these variables
 
   
 
   
 
  gui1()
 
  gui1()
Line 171: Line 171:
 
     $hGUI1 = GUICreate("Gui 1", 200, 200, 100, 100)
 
     $hGUI1 = GUICreate("Gui 1", 200, 200, 100, 100)
 
     GUISetOnEvent($GUI_EVENT_CLOSE, "On_Close_Main") ; Run this function when the main GUI [X] is clicked
 
     GUISetOnEvent($GUI_EVENT_CLOSE, "On_Close_Main") ; Run this function when the main GUI [X] is clicked
     $hButton1 = GUICtrlCreateButton("Msgbox 1", 10, 10, 80, 30)
+
     $idButton1 = GUICtrlCreateButton("Msgbox 1", 10, 10, 80, 30)
 
     GUICtrlSetOnEvent(-1, "On_Button1")
 
     GUICtrlSetOnEvent(-1, "On_Button1")
     $hButton2 = GUICtrlCreateButton("Show Gui 2", 10, 60, 80, 30)
+
     $idButton2 = GUICtrlCreateButton("Show Gui 2", 10, 60, 80, 30)
 
     GUICtrlSetOnEvent(-1, "On_Button2")
 
     GUICtrlSetOnEvent(-1, "On_Button2")
 
     GUISetState()
 
     GUISetState()
Line 185: Line 185:
 
     $hGUI2 = GUICreate("Gui 2", 200, 200, 350, 350)
 
     $hGUI2 = GUICreate("Gui 2", 200, 200, 350, 350)
 
     GUISetOnEvent($GUI_EVENT_CLOSE, "On_Close_Secondary") ; Run this function when the secondary GUI [X] is clicked
 
     GUISetOnEvent($GUI_EVENT_CLOSE, "On_Close_Secondary") ; Run this function when the secondary GUI [X] is clicked
     $hButton3 = GUICtrlCreateButton("MsgBox 2", 10, 10, 80, 30)
+
     $idButton3 = GUICtrlCreateButton("MsgBox 2", 10, 10, 80, 30)
 
     GUICtrlSetOnEvent(-1, "On_Button3")
 
     GUICtrlSetOnEvent(-1, "On_Button3")
 
     GUISetState()
 
     GUISetState()
Line 196: Line 196:
 
  Func On_Close_Secondary()
 
  Func On_Close_Secondary()
 
     GUIDelete($hGUI2)
 
     GUIDelete($hGUI2)
     GUICtrlSetState($hButton2, $GUI_ENABLE)
+
     GUICtrlSetState($idButton2, $GUI_ENABLE)
 
  EndFunc
 
  EndFunc
 
   
 
   
Line 204: Line 204:
 
   
 
   
 
  Func On_Button2()
 
  Func On_Button2()
     GUICtrlSetState($hButton2, $GUI_DISABLE)
+
     GUICtrlSetState($idButton2, $GUI_DISABLE)
 
     gui2()
 
     gui2()
 
  EndFunc
 
  EndFunc
Line 216: Line 216:
 
  Opt("GUIOnEventMode", 1)
 
  Opt("GUIOnEventMode", 1)
 
   
 
   
  Global $hGUI1, $hGUI2 = 9999, $hButton1, $hButton2, $hButton3 = 9999 ; Predeclare the variables with dummy values to prevent firing the Case statements
+
  Global $hGUI1, $hGUI2 = 9999, $idButton1, $idButton2, $idButton3 = 9999 ; Predeclare the variables with dummy values to prevent firing the Case statements
 
   
 
   
 
  gui1()
 
  gui1()
Line 223: Line 223:
 
     $hGUI1 = GUICreate("Gui 1", 200, 200, 100, 100)
 
     $hGUI1 = GUICreate("Gui 1", 200, 200, 100, 100)
 
     GUISetOnEvent($GUI_EVENT_CLOSE, "On_Close") ; Call a common GUI close function
 
     GUISetOnEvent($GUI_EVENT_CLOSE, "On_Close") ; Call a common GUI close function
     $hButton1 = GUICtrlCreateButton("Msgbox 1", 10, 10, 80, 30)
+
     $idButton1 = GUICtrlCreateButton("Msgbox 1", 10, 10, 80, 30)
 
     GUICtrlSetOnEvent(-1, "On_Button") ; Call a common button function
 
     GUICtrlSetOnEvent(-1, "On_Button") ; Call a common button function
     $hButton2 = GUICtrlCreateButton("Show Gui 2", 10, 60, 80, 30)
+
     $idButton2 = GUICtrlCreateButton("Show Gui 2", 10, 60, 80, 30)
 
     GUICtrlSetOnEvent(-1, "On_Button") ; Call a common button function
 
     GUICtrlSetOnEvent(-1, "On_Button") ; Call a common button function
 
     GUISetState()
 
     GUISetState()
Line 237: Line 237:
 
     $hGUI2 = GUICreate("Gui 2", 200, 200, 350, 350)
 
     $hGUI2 = GUICreate("Gui 2", 200, 200, 350, 350)
 
     GUISetOnEvent($GUI_EVENT_CLOSE, "On_Close") ; Call a common GUI close function
 
     GUISetOnEvent($GUI_EVENT_CLOSE, "On_Close") ; Call a common GUI close function
     $hButton3 = GUICtrlCreateButton("MsgBox 2", 10, 10, 80, 30)
+
     $idButton3 = GUICtrlCreateButton("MsgBox 2", 10, 10, 80, 30)
 
     GUICtrlSetOnEvent(-1, "On_Button") ; Call a common button function
 
     GUICtrlSetOnEvent(-1, "On_Button") ; Call a common button function
 
     GUISetState()
 
     GUISetState()
Line 248: Line 248:
 
         Case $hGUI2
 
         Case $hGUI2
 
             GUIDelete($hGUI2) ; If it was this GUI - we just delete the GUI <<<<<<<<<<<<<<<
 
             GUIDelete($hGUI2) ; If it was this GUI - we just delete the GUI <<<<<<<<<<<<<<<
             GUICtrlSetState($hButton2, $GUI_ENABLE)
+
             GUICtrlSetState($idButton2, $GUI_ENABLE)
 
     EndSwitch
 
     EndSwitch
 
  EndFunc
 
  EndFunc
Line 254: Line 254:
 
  Func On_Button()
 
  Func On_Button()
 
     Switch @GUI_CTRLID ; See which button sent the message
 
     Switch @GUI_CTRLID ; See which button sent the message
         Case $hButton1
+
         Case $idButton1
 
             MessageBox(1) ; We can call a function with parameters here <<<<<<<<<<<<<<<<<<<
 
             MessageBox(1) ; We can call a function with parameters here <<<<<<<<<<<<<<<<<<<
         Case $hButton2
+
         Case $idButton2
             GUICtrlSetState($hButton2, $GUI_DISABLE)
+
             GUICtrlSetState($idButton2, $GUI_DISABLE)
 
             gui2()
 
             gui2()
         Case $hButton3
+
         Case $idButton3
 
             MessageBox(2) ; We can call a function with parameters here <<<<<<<<<<<<<<<<<<<
 
             MessageBox(2) ; We can call a function with parameters here <<<<<<<<<<<<<<<<<<<
 
     EndSwitch
 
     EndSwitch

Revision as of 18:56, 16 April 2017

Introduction

Having several GUIs on the screen at the same time is fairly common but structuring your code to deal with this can seem quite daunting. However, as I hope this tutorial will demonstrate, it is nowhere near as difficult as it first appears.

MessageLoop Mode

Let us start with MessageLoop mode as this is where most new coders run into difficulties with multiple GUIs. This example script illustrates the problem - it exits when the [X] is clicked on either GUI:

 #include <GUIConstantsEx.au3>
 
 Global $idButton3 = 9999
 
 gui1()
 
 Func gui1()
     $hGUI1 = GUICreate("Gui 1", 200, 200, 100, 100)
     $idButton1 = GUICtrlCreateButton("Msgbox 1", 10, 10, 80, 30)
     $idButton2 = GUICtrlCreateButton("Show Gui 2", 10, 60, 80, 30)
     GUISetState()
 
     While 1
         Switch GUIGetMsg()
             Case $GUI_EVENT_CLOSE
                 ExitLoop
             Case $idButton1
                 MsgBox("", "MsgBox 1", "Test from Gui 1")
             Case $idButton2
                 GUICtrlSetState($idButton2, $GUI_DISABLE)
                 gui2()
             Case $idButton3
                 MsgBox("", "MsgBox 2", "Test from Gui 2") 
         EndSwitch
     WEnd
 EndFunc   ;==>gui1
 
 Func gui2()
     $hGUI2 = GUICreate("Gui 2", 200, 200, 350, 350)
     $idButton3 = GUICtrlCreateButton("MsgBox 2", 10, 10, 80, 30)
     GUISetState()
 EndFunc   ;==>gui2

The script exits because it has a single GUIGetMsg loop and the $GUI_EVENT_CLOSE message is received when either [X] is clicked - we have no way of telling the messages from the two GUIs apart.

The simplest solution is to disable the first GUI while the second is displayed:

 #include <GUIConstantsEx.au3>
 
 gui1()
 
 Func gui1()
     $hGUI1 = GUICreate("Gui 1", 200, 200, 100, 100)
     $idButton1 = GUICtrlCreateButton("Msgbox 1", 10, 10, 80, 30)
     $idButton2 = GUICtrlCreateButton("Show Gui 2", 10, 60, 80, 30)
     GUISetState()
 
     While 1
         Switch GUIGetMsg()
             Case $GUI_EVENT_CLOSE
                 ExitLoop
             Case $idButton1
                 MsgBox("", "MsgBox 1", "Test from Gui 1")
             Case $idButton2
                 ; Disable the first GUI
                 GUISetState(@SW_DISABLE, $hGUI1)
                 gui2()
                 ; Re-enable the first GUI
                 GUISetState(@SW_ENABLE, $hGUI1)
         EndSwitch
     WEnd
 EndFunc   ;==>gui1
 
 Func gui2()
     $hGUI2 = GUICreate("Gui 2", 200, 200, 350, 350)
     $idButton3 = GUICtrlCreateButton("MsgBox 2", 10, 10, 80, 30)
     GUISetState()
 
     While 1
         ; We can only get messages from the second GUI
         Switch GUIGetMsg()
             Case $GUI_EVENT_CLOSE
                 GUIDelete($hGUI2)
                 ExitLoop
             Case $idButton3
                 MsgBox("", "MsgBox 2", "Test from Gui 2")
 		EndSwitch
 	WEnd
 EndFunc   ;==>gui2

This may well be all you need, but it does mean that we cannot action any of the controls on the first GUI until we close the second. And importantly we remain blocked in the While...WEnd loop within the gui2 function - go and read the Interrupting a running function tutorial to see why this is less than ideal.

So how can we deal with multiple GUIs visible at the same time? Fortunately AutoIt offers us a simple way to differentiate between GUIs in MessageLoop mode. Normally we use code like this in our idle loop to detect the messages sent by our GUI and its controls:

 Switch GUIGetMsg()
     Case $GUI_EVENT_CLOSE
         ; Code
     Case $idButton1
         ; Code
 EndSwitch

But when dealing with multiple GUIs, we need to use the "advanced" parameter when we call GUIGetMsg. As explained in the Help file, the function then returns an array instead of a single value. This array includes information on what exactly triggered the message, just what we need to distinguish the message that was sent (element[0] of the array) and which GUI sent it (element[1]). We can then amend our simple Switch statement above to read like this:

 $aMsg = GUIGetMsg(1) ; Use advanced parameter to get an array returned

 Switch $aMsg[1] ; First check which GUI sent the message
     Case $hGUI1
         Switch $aMsg[0] ; Now check for the messages sent from $hGUI1
             Case $GUI_EVENT_CLOSE 
                 ; Code
             Case $hControl
                 ; Code
         EndSwitch
     Case $hGUI2
         Switch $aMsg[0] ; Now check for the messages sent from $hGUI2
             Case $GUI_EVENT_CLOSE
                 ; Code
             Case $idButton3
                 ; Code
         EndSwitch
 EndSwitch

Although this looks complicated, if you take a moment to study it and you will quickly realise it is simply two Switch structures within an outer Switch. You have already dealt with a single Switch structure for a single GUI. All you are doing here is determining which Switch structure you want to use, and that depends on the GUI which sent the message which is why we need the outer Switch structure as a wrapper.

So here is an example of how to manage two GUIs simultaneously using the "advanced" parameter with GUIGetMsg:

 #include <GUIConstantsEx.au3>
 
 Global $hGUI2 = 9999, $idButton3 ; Predeclare the variables with dummy values to prevent firing the Case statements, only for GUI this time
 
 gui1()
 
 Func gui1()
     $hGUI1 = GUICreate("Gui 1", 200, 200, 100, 100)
     $idButton1 = GUICtrlCreateButton("Msgbox 1", 10, 10, 80, 30)
     $idButton2 = 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 $idButton1
                         MsgBox("", "MsgBox 1", "Test from Gui 1")
                     Case $idButton2
                         GUICtrlSetState($idButton2, $GUI_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 <<<<<<<<<<<<<<<
                         GUIDelete($hGUI2)
                         GUICtrlSetState($idButton2, $GUI_ENABLE)
                     Case $idButton3
                         MsgBox("", "MsgBox", "Test from Gui 2")
                 EndSwitch
         EndSwitch
     WEnd
 EndFunc   ;==>gui1
 
 Func gui2()
     $hGUI2 = GUICreate("Gui 2", 200, 200, 350, 350)
     $idButton3 = GUICtrlCreateButton("MsgBox 2", 10, 10, 80, 30)
     GUISetState()
 EndFunc   ;==>gui2

As you can see, we have a single While...WEnd loop which distinguishes between the two GUIs, both GUIs and their controls remain active and we stay in the main idle loop while we wait (you did read that other tutorial I hope!).

OnEvent Mode

Coders using OnEvent mode do not usually find the same problem with multiple GUIs as they can code separate functions for each $GUI_EVENT_CLOSE as shown here:

 #include <GUIConstantsEx.au3>
 
 Opt("GUIOnEventMode", 1)
 
 Global $hGUI2, $idButton2 ; Predeclare these variables
 
 gui1()
 
 Func gui1()
     $hGUI1 = GUICreate("Gui 1", 200, 200, 100, 100)
     GUISetOnEvent($GUI_EVENT_CLOSE, "On_Close_Main") ; Run this function when the main GUI [X] is clicked
     $idButton1 = GUICtrlCreateButton("Msgbox 1", 10, 10, 80, 30)
     GUICtrlSetOnEvent(-1, "On_Button1")
     $idButton2 = GUICtrlCreateButton("Show Gui 2", 10, 60, 80, 30)
     GUICtrlSetOnEvent(-1, "On_Button2")
     GUISetState()
 
     While 1
         Sleep(10)
     WEnd
 EndFunc   ;==>gui1
 
 Func gui2()
     $hGUI2 = GUICreate("Gui 2", 200, 200, 350, 350)
     GUISetOnEvent($GUI_EVENT_CLOSE, "On_Close_Secondary") ; Run this function when the secondary GUI [X] is clicked
     $idButton3 = GUICtrlCreateButton("MsgBox 2", 10, 10, 80, 30)
     GUICtrlSetOnEvent(-1, "On_Button3")
     GUISetState()
 EndFunc   ;==>gui2
 
 Func On_Close_Main()
     Exit
 EndFunc
 
 Func On_Close_Secondary()
     GUIDelete($hGUI2)
     GUICtrlSetState($idButton2, $GUI_ENABLE)
 EndFunc
 
 Func On_Button1()
     MsgBox("", "MsgBox 1", "Test from Gui 1")
 EndFunc
 
 Func On_Button2()
     GUICtrlSetState($idButton2, $GUI_DISABLE)
     gui2()
 EndFunc
 
 Func On_Button3()
     MsgBox("", "MsgBox 2", "Test from Gui 2")
 EndFunc

But did you realise that you can also use what some people think of as a hybrid mode - using common OnEvent functions and then determining the specific GUI or control which called the function within the function? As an added bonus, this approach may, depending on the circumstances, let you send parameters to the functions you call - something that you normally cannot do in OnEvent mode.

 #include <GUIConstantsEx.au3>
 
 Opt("GUIOnEventMode", 1)
 
 Global $hGUI1, $hGUI2 = 9999, $idButton1, $idButton2, $idButton3 = 9999 ; Predeclare the variables with dummy values to prevent firing the Case statements
 
 gui1()
 
 Func gui1()
     $hGUI1 = GUICreate("Gui 1", 200, 200, 100, 100)
     GUISetOnEvent($GUI_EVENT_CLOSE, "On_Close") ; Call a common GUI close function
     $idButton1 = GUICtrlCreateButton("Msgbox 1", 10, 10, 80, 30)
     GUICtrlSetOnEvent(-1, "On_Button") ; Call a common button function
     $idButton2 = GUICtrlCreateButton("Show Gui 2", 10, 60, 80, 30)
     GUICtrlSetOnEvent(-1, "On_Button") ; Call a common button function
     GUISetState()
 
     While 1
         Sleep(10)
     WEnd
 EndFunc   ;==>gui1
 
 Func gui2()
     $hGUI2 = GUICreate("Gui 2", 200, 200, 350, 350)
     GUISetOnEvent($GUI_EVENT_CLOSE, "On_Close") ; Call a common GUI close function
     $idButton3 = GUICtrlCreateButton("MsgBox 2", 10, 10, 80, 30)
     GUICtrlSetOnEvent(-1, "On_Button") ; Call a common button function
     GUISetState()
 EndFunc   ;==>gui2
 
 Func On_Close()
     Switch @GUI_WINHANDLE ; See which GUI sent the CLOSE message
         Case $hGUI1
             Exit ; If it was this GUI - we exit <<<<<<<<<<<<<<<
         Case $hGUI2
             GUIDelete($hGUI2) ; If it was this GUI - we just delete the GUI <<<<<<<<<<<<<<<
             GUICtrlSetState($idButton2, $GUI_ENABLE)
     EndSwitch
 EndFunc
 
 Func On_Button()
     Switch @GUI_CTRLID ; See which button sent the message
         Case $idButton1
             MessageBox(1) ; We can call a function with parameters here <<<<<<<<<<<<<<<<<<<
         Case $idButton2
             GUICtrlSetState($idButton2, $GUI_DISABLE)
             gui2()
         Case $idButton3
             MessageBox(2) ; We can call a function with parameters here <<<<<<<<<<<<<<<<<<<
     EndSwitch
 EndFunc
 
 Func MessageBox($iIndex)
     MsgBox("", "MsgBox " & $iIndex, "Test from Gui " & $iIndex)
 EndFunc

Summary

So you see that managing multiple GUIS is not as difficult as you might think. One of these methods is bound to suit your script, but do not try and mix them - only one method per script please!