Tabs

From AutoIt Wiki
Jump to navigation Jump to search

Tabs And How To Deal With Them

Tabs are a valuable tool when you need to fit a lot of controls into a small GUI. But inexperienced users often have problems with them - particularly in making sure that controls only appear on the correct tab. This tutorial should help. Before going further, it is important to understand the differences between controls created using the built-in AutoIt commands (GUICtrlCreate*) and those created with the UDFs. The built-in commands produce controls which are managed internally by AutoIt - they return ControlIDs. The UDF commands create controls that are not in Autoit's internal management structure and need to be managed by the code - they normally return handles (the special unique identifier for all Windows components).

Tabs Created With Native AutoIt Functions

Any tabs created by the built-in AutoIt commands GUICtrlCreateTab/TabItem will automatically take care of displaying any built-in controls created at the same time within the tab creation structure. Here is an example:

#include <GUIConstantsEx.au3>

$hGUI = GUICreate("Built-In Tab Example", 500, 500)

$hTab = GUICtrlCreateTab(10, 10, 480, 480)
; Create tabitems
For $i = 0 To 2
    GUICtrlCreateTabItem("Tab " & $i)
    GUICtrlCreateButton("Button " & $i, 20 + ($i * 100), 40 + ($i * 50), 80, 30)
Next
; Close Tab definiton
GUICtrlCreateTabItem("") 

GUISetState()

While 1
    Switch GUIGetMsg()
        Case $GUI_EVENT_CLOSE
            Exit
    EndSwitch
WEnd

As you can see, the controls for each tab are created just after the TabItem on which they are to appear and before the next TabItem. Do not forget to close the Tab definition - many tab problems are caused by omitting this vital line.

What happens if we add some UDF created controls to these tabs?

 #include <GUIConstantsEx.au3>
 #Include <GuiButton.au3>
 
 $hGUI = GUICreate("Built-In Tab Example", 500, 500)
 
 $hTab = GUICtrlCreateTab(10, 10, 480, 480)
 ; Create tabitems
 For $i = 0 To 2
     GUICtrlCreateTabItem("Tab " & $i)
     GUICtrlCreateButton("Built-In " & $i, 20 + ($i * 100), 40 + ($i * 50), 80, 30)
     _GUICtrlButton_Create($hGUI, "UDF " & $i, 20 + ($i * 100), 80 + ($i * 50),80, 30)
 Next
 ; Close Tab definiton
 GUICtrlCreateTabItem("")
 
 GUISetState()
 
 While 1
     Switch GUIGetMsg()
         Case $GUI_EVENT_CLOSE
             Exit
     EndSwitch
 WEnd

As you can see, the UDF created controls appear on every tab. Remember this is because they are not part of the internal AutoIt control management structure, so AutoIt does not know how to handle them. It is up to you to manage them by seeing which tab is active and hiding/showing these controls as required:

 #include <GUIConstantsEx.au3>
 #Include <GuiButton.au3>
 
 Global $hButtons[3]
 
 $hGUI = GUICreate("Built-In Tab Example", 500, 500)
 
 $hTab = GUICtrlCreateTab(10, 10, 480, 480)
 ; Create tabitems
 For $i = 0 To 2
     GUICtrlCreateTabItem("Tab " & $i)
     GUICtrlCreateButton("Built-In " & $i, 20 + ($i * 100), 40 + ($i * 50), 80, 30)
     ; Add a label to the first tab
     If $i = 0 Then GUICtrlCreateLabel("See how 'laggy' the UDF buttons are when selecting this tab because of using WinSetState", 20, 200, 150, 60)
 Next
 
 GUICtrlCreateTabItem("")
 
 ; Create UDF controls
 For $i = 0 To 2
     $hButtons[$i] = _GUICtrlButton_Create($hGUI, "UDF " & $i, 20 + ($i * 100), 80 + ($i * 50),80, 30)
 Next
 
 ; Hide the controls so only the one on the first tab is visible
 WinSetState($hButtons[1], "", @SW_HIDE)
 WinSetState($hButtons[2], "", @SW_HIDE)
 
 GUISetState()
 
 ; This is the current active tab
 $iLastTab = 0
 
 While 1
     Switch GUIGetMsg()
         Case $GUI_EVENT_CLOSE
             Exit
         Case $hTab
             ; Check which Tab is active
             $iCurrTab = GUICtrlRead($hTab)
             ; If the Tab has changed
             If $iCurrTab <> $iLastTab Then
                 ; Show/Hide controls as required
                 Switch $iCurrTab
                     Case 0
                         ; Note lag when WinSetState is used
                         WinSetState($hButtons[1], "", @SW_HIDE)
                         WinSetState($hButtons[2], "", @SW_HIDE)
                         WinSetState($hButtons[0], "", @SW_SHOW)
                     Case 1
                         ; No lag when using ControlHide/Show
                         ControlHide($hGUI, "", $hButtons[0])
                         ControlHide($hGUI, "", $hButtons[2])
                         ControlShow($hGUI, "", $hButtons[1])
                     Case 2
                         ; Nor when using this DLL
                         DllCall("User32.dll", "bool", "ShowWindowAsync", "hwnd", $hButtons[0], "int", @SW_HIDE)
                         DllCall("User32.dll", "bool", "ShowWindowAsync", "hwnd", $hButtons[1], "int", @SW_HIDE)
                         DllCall("User32.dll", "bool", "ShowWindowAsync", "hwnd", $hButtons[2], "int", @SW_SHOW)
 
                 EndSwitch
                 ; Store the value for future comparisons
                 $iLastTab = $iCurrTab
             EndIf
     EndSwitch
 WEnd

Note the lag in hiding/showing the UDF created controls if you use WinSetState - I would recommend using ControlShow/Hide which gives an instantaneous response. Also how you do not need to create the UDF controls within the tab creation structure - as you have to look after them, there is no requirement to do so.

Tabs Created With UDFs

Now let us look at Tabs created with the GUITab UDF. In this case you need to manage all of the controls on the tabs yourself, even if they are created using the built-in commands:

 #include <GUIConstantsEx.au3>
 #Include <GuiButton.au3>
 #include <GuiTab.au3>
 
 Global $hBuiltIn_Buttons[3]
 Global $hUDF_Buttons[3]
 
 $hGUI = GUICreate("Built-In Tab Example", 500, 500)
 
 $hTab = _GUICtrlTab_Create($hGUI, 10, 10, 480, 480)
 GUISetState()
 
 ; Add tabs
 _GUICtrlTab_InsertItem($hTab, 0, "Tab 0")
 _GUICtrlTab_InsertItem($hTab, 1, "Tab 1")
 _GUICtrlTab_InsertItem($hTab, 2, "Tab 2")
 
 ; Create the Built-in and UDF buttons
 For $i = 0 To 2
     $hBuiltIn_Buttons[$i] = GUICtrlCreateButton("Button " & $i, 20 + ($i * 100), 40 + ($i * 50), 80, 30)
     $hUDF_Buttons[$i] = _GUICtrlButton_Create($hGUI, "UDF " & $i, 20 + ($i * 100), 80 + ($i * 50),80, 30)
 Next
 
 ; Hide the controls so only the one on the first tab is visible
 GUICtrlSetState($hBuiltIn_Buttons[1], $GUI_HIDE)
 GUICtrlSetState($hBuiltIn_Buttons[2], $GUI_HIDE)
 ControlHide($hGUI, "", $hUDF_Buttons[1])
 ControlHide($hGUI, "", $hUDF_Buttons[2])
 
 GUISetState()
 
 ; This is the current active tab
 $iLastTab = 0
 
 While 1
     Switch GUIGetMsg()
         Case $GUI_EVENT_CLOSE
             Exit
     EndSwitch
 
     ; Check which Tab is active
     $iCurrTab = _GUICtrlTab_GetCurFocus($hTab)
     ; If the Tab has changed
     If $iCurrTab <> $iLastTab Then
         ; Store the value for future comparisons
         $iLastTab = $iCurrTab
         ; Show/Hide controls as required
         Switch $iCurrTab
             Case 0
                 GUICtrlSetState($hBuiltIn_Buttons[1], $GUI_HIDE)
                 GUICtrlSetState($hBuiltIn_Buttons[2], $GUI_HIDE)
                 GUICtrlSetState($hBuiltIn_Buttons[0], $GUI_SHOW)
                 ControlHide($hGUI, "", $hUDF_Buttons[1])
                 ControlHide($hGUI, "", $hUDF_Buttons[2])
                 ControlShow($hGUI, "", $hUDF_Buttons[0])
             Case 1
                 GUICtrlSetState($hBuiltIn_Buttons[0], $GUI_HIDE)
                 GUICtrlSetState($hBuiltIn_Buttons[2], $GUI_HIDE)
                 GUICtrlSetState($hBuiltIn_Buttons[1], $GUI_SHOW)
                 ControlHide($hGUI, "", $hUDF_Buttons[0])
                 ControlHide($hGUI, "", $hUDF_Buttons[2])
                 ControlShow($hGUI, "", $hUDF_Buttons[1])
            Case 2
                 GUICtrlSetState($hBuiltIn_Buttons[0], $GUI_HIDE)
                 GUICtrlSetState($hBuiltIn_Buttons[1], $GUI_HIDE)
                 GUICtrlSetState($hBuiltIn_Buttons[2], $GUI_SHOW)
                 ControlHide($hGUI, "", $hUDF_Buttons[0])
                 ControlHide($hGUI, "", $hUDF_Buttons[1])
                 ControlShow($hGUI, "", $hUDF_Buttons[2])
         EndSwitch
     EndIf
 WEnd

A lot of work but a very satisfactory result. Note the need to use different commands to hide/show the built-in and UDF created controls to avoid "lag" on the latter as was shown in the earlier example.

So, a couple of lessons to draw from this:

- 1. When using tabs, try and use built-in commands if at all possible. If you do, AutoIt looks after the showing/hiding problem for you as long as you create the controls within the tab creation structure. See the next section for how to add controls to tabs after their creation.

- 2. If you must use UDF created controls for any reason, you have to manage hiding/showing all controls yourself.

Adding Controls To Tabs After Creation

If you need to add built-in controls to a tab after the tabs have already been created, then you must use GUISwitch with the tabitemID parameter to select the correct tab before you create the control or you will find that it is visible on all tabs.

Here is an example to show how to do it:

#include <GUIConstantsEx.au3>

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

$cTab = GUICtrlCreateTab(10, 10, 480, 350)
$cTab_0 = GUICtrlCreateTabItem("Tab 0")
$cTab_1 = GUICtrlCreateTabItem("Tab 1")
GUICtrlCreateTabItem("")

$cButton = GUICtrlCreateButton("Add controls", 10, 450, 80, 30)

GUISetState()

While 1
	Switch GUIGetMsg()
		Case $GUI_EVENT_CLOSE
			Exit
		Case $cButton
			; Correct
			GUISwitch($hGUI, $cTab_0)
			GUICtrlCreateLabel("Only on Tab 0", 40, 40, 200, 20)
			GUICtrlSetBkColor(-1, 0xCCFFCC)
			GUICtrlCreateTabItem("")
			GUISwitch($hGUI)
			; Incorrect
			GUICtrlCreateLabel("OnTab 0 AND Tab 1", 40, 100, 200, 20)
			GUICtrlSetBkColor(-1, 0xFFCCCC)
	EndSwitch
WEnd

Do not forget to reclose the tab definition after adding the new controls.

Multiple Tabs In A GUI

Unfortunately, only one built-in tab control can be created per GUI - you cannot have several tabs on a single GUI. But there is a way around this - just create child GUIs which can each hold a tab:

#include <GUIConstantsEx.au3>
 #include <WindowsConstants.au3>
 
 $hGUI = GUICreate("Test", 500, 500)
 
 GUISetState()
 
 ; Create child GUIs to hold tabs
 $hTab_Win0 = GUICreate("", 400, 200, 50, 20, $WS_POPUP, $WS_EX_MDICHILD, $hGUI)
 $hTab_0 = GUICtrlCreateTab(10, 10, 380, 180)
     $hTab_00 = GUICtrlCreateTabitem("00")
         GUICtrlCreateButton("00", 160, 90, 80, 30)
     $hTab_01 = GUICtrlCreateTabitem("01")
         GUICtrlCreateButton("01", 160, 90, 80, 30)
 
 GUICtrlCreateTabitem ("")
 GUISetState()
 
 $hTab_Win1 = GUICreate("", 400, 200, 50, 250, $WS_POPUP, $WS_EX_MDICHILD, $hGUI)
 $hTab_1 = GUICtrlCreateTab(10, 10, 380, 180)
     $hTab_10 = GUICtrlCreateTabitem("10")
         GUICtrlCreateButton("10", 160, 90, 80, 30)
     $hTab_11 = GUICtrlCreateTabitem("11")
         GUICtrlCreateButton("11", 160, 90, 80, 30)
 GUICtrlCreateTabitem ("")
 GUISetState()
 
 While 1
     Switch GUIGetMsg()
         Case $GUI_EVENT_CLOSE
             Exit
     EndSwitch
 WEnd

Easy when you know how!


Tab switching with CTRL+TAB / CTRL+SHIFT+TAB

#include <GUIConstantsEx.au3>
#include <TabConstants.au3>

Global $aTab[3]

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

$cTab = GUICtrlCreateTab(10, 10, 480, 200)

$aTab[0] = GUICtrlCreateTabItem("Tab 0")
$aTab[1] = GUICtrlCreateTabItem("Tab 1")
$aTab[2] = GUICtrlCreateTabItem("Tab 2")
GUICtrlCreateTabItem("")

$cTab_Right = GUICtrlCreateDummy()
$cTab_Left = GUICtrlCreateDummy()

GUISetState()

Global $aAccelKeys[2][2] = [["^{TAB}", $cTab_Right],["^+{TAB}", $cTab_Left]]
GUISetAccelerators($aAccelKeys)

While 1
    Switch GUIGetMsg()
        Case $GUI_EVENT_CLOSE
            Exit
        Case $cTab_Right
            $iTab = GUICtrlRead($cTab) + 1
            If $iTab > (UBound($aTab) - 1) Then $iTab = 0
            GUICtrlSendMsg($cTab, $TCM_SETCURFOCUS, $iTab, 0) 
        Case $cTab_Left
            $iTab = GUICtrlRead($cTab) - 1
            If $iTab < 0 Then $iTab = UBound($aTab) - 1
            GUICtrlSendMsg($cTab, $TCM_SETCURFOCUS, $iTab, 0) 
    EndSwitch
WEnd

Based on Melba23 code from Tab switching with CTRL+TAB / CTRL+SHIFT+TAB

Related links

Below Links to interesting topics in the forum related to the use of Tab

Summary

Tabs are useful controls, but can be difficult to master. After this tutorial you should be well on your way!