Tabs: Difference between revisions
No edit summary |
m (Added wiki headers, minor typos) |
||
Line 1: | Line 1: | ||
=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. | 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 '''ControlID'''s. 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: | 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: | ||
<syntaxhighlight lang="autoit"> | <syntaxhighlight lang="autoit"> | ||
#include <GUIConstantsEx.au3> | #include <GUIConstantsEx.au3> | ||
Line 32: | Line 29: | ||
WEnd | WEnd | ||
</syntaxhighlight> | </syntaxhighlight> | ||
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. | 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? | What happens if we add some UDF created controls to these tabs? | ||
<syntaxhighlight lang="autoit"> | <syntaxhighlight lang="autoit"> | ||
#include <GUIConstantsEx.au3> | #include <GUIConstantsEx.au3> | ||
Line 62: | Line 57: | ||
WEnd | WEnd | ||
</syntaxhighlight> | </syntaxhighlight> | ||
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: | 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: | ||
<syntaxhighlight lang="autoit"> | <syntaxhighlight lang="autoit"> | ||
#include <GUIConstantsEx.au3> | #include <GUIConstantsEx.au3> | ||
Line 132: | Line 125: | ||
WEnd | WEnd | ||
</syntaxhighlight> | </syntaxhighlight> | ||
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. | 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: | 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: | ||
<syntaxhighlight lang="autoit"> | <syntaxhighlight lang="autoit"> | ||
#include <GUIConstantsEx.au3> | #include <GUIConstantsEx.au3> | ||
Line 211: | Line 204: | ||
WEnd | WEnd | ||
</syntaxhighlight> | </syntaxhighlight> | ||
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. | 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: | 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 | - 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. If you need to add controls after having ended the tab structure definiton, 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. | ||
- 2. If you must use UDF created controls for any reason, you have to manage hiding/showing all controls yourself. | - 2. If you must use UDF created controls for any reason, you have to manage hiding/showing all controls yourself. | ||
=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: | 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: | ||
<syntaxhighlight lang="autoit"> | <syntaxhighlight lang="autoit"> | ||
#include <GUIConstantsEx.au3> | #include <GUIConstantsEx.au3> | ||
Line 259: | Line 250: | ||
WEnd | WEnd | ||
</syntaxhighlight> | </syntaxhighlight> | ||
Easy when you know how! | Easy when you know how! | ||
=Summary= | |||
Tabs are useful controls, but can be difficult to master. After this tutorial you should be well on your way! | Tabs are useful controls, but can be difficult to master. After this tutorial you should be well on your way! |
Revision as of 14:10, 11 November 2012
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. If you need to add controls after having ended the tab structure definiton, 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.
- 2. If you must use UDF created controls for any reason, you have to manage hiding/showing all controls yourself.
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!
Summary
Tabs are useful controls, but can be difficult to master. After this tutorial you should be well on your way!