AndyS01

How to prohibit switching Tabs on Tab control

4 posts in this topic

I have a script that uses the Tab control with 3 tabs on it and I want to ignore clicks on the other tabs if I have certain items selected on the current tab.

I'm pretty sure I can do it in WM_NOTIFY handler, but I've tried and failed to detect the Tab switch notification.
here is my test script:

#include <Debug.au3>
_DebugSetup(@ScriptName & "_debug.txt", False, 5, "") ; 6 = Notepad; 2 = to console; 4 = to a file
_DebugOut("=============== " & @MON & "/" & @MDAY & "/" & @YEAR & " " & @HOUR & ":" & @MIN & ":" & @SEC & " ====================" & @CRLF)

#NoTrayIcon
#Region ;**** Directives created by AutoIt3Wrapper_GUI ****
#AutoIt3Wrapper_UseUpx=n
#AutoIt3Wrapper_Au3Check_Parameters=-d -w 1 -w 2 -w 3 -w 4 -w 5 -w 6
#AutoIt3Wrapper_UseX64=N
#EndRegion ;**** Directives created by AutoIt3Wrapper_GUI ****

#include <Array.au3>
#include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>
#include <GuiTab.au3>
#include <GuiListView.au3>

Opt("GUICloseOnESC", 1) ; ESC closes GUI? (0 = no, 1 = yes)
Opt("GUIOnEventMode", 1) ; Change to OnEvent mode
Opt('MustDeclareVars', 1)
OnAutoItExitRegister("Event_GUIClose")
Opt("GUIEventOptions", 1) ;0=default, 1=just notification, 2=GuiCtrlRead tab index
Opt("WinTitleMatchMode", -2) ;1=start, 2=subStr, 3=exact, 4=advanced, -1 to -4=Nocase

Global $hMainWin = 0
Global $hTab = 0
Global $aIDs = StringSplit("", "")
Global $ahWnds = StringSplit("", "")
Global $aTypes = StringSplit("", "")
Global $iCounter = 0

_Main()
Exit (0)

Func _Main()

    $hMainWin = 0

    CreateAllControls()

    fillListViews()

    GUISetOnEvent($GUI_EVENT_CLOSE, 'Event_GUIClose')
    GUIRegisterMsg($WM_NOTIFY, "WM_NOTIFY")

    GUISetState(@SW_SHOW) ; Make everything visible

    While 1
        Sleep(250)
    WEnd

    Exit (0)
EndFunc   ;==>_Main

Func WM_NOTIFY($hWnd, $iMsg, $iwParam, $ilParam)
    ;_DebugOut("+++:[" & $iCounter & "]: WM_NOTIFY(" & Hex($hWnd) & "|" & Hex($iMsg) & "|" & Hex($iwParam) & "|" & Hex($ilParam) & ") entered")
    Local $iCode, $tNMHDR, $param, $ret, $hWndFrom
    #forceref $hWnd, $iMsg, $iwParam, $param, $ret, $hWndFrom, $iCode
    $iCounter += 1

    $tNMHDR = DllStructCreate($tagNMHDR, $ilParam)
    $hWndFrom = HWnd(DllStructGetData($tNMHDR, "hWndFrom"))
    $iCode = DllStructGetData($tNMHDR, "Code")
    ;_DebugOut("+++: $iCode = " & $iCode)

    ; -12 = $NM_CUSTOMDRAW

    Return $GUI_RUNDEFMSG
EndFunc   ;==>WM_NOTIFY

Func CreateAllControls()
    Local $mw, $mh, $iID_Menu

    ; Create the Main window first
    $mw = 600
    $mh = 400
    $hMainWin = GUICreate("Test 7", $mw, $mh, 383, 54)

    ; Create the File menu and it's choices
    $iID_Menu = GUICtrlCreateMenu("&File")
    GUICtrlCreateMenuItem("", $iID_Menu)
    GUICtrlCreateMenuItem("a-Exit", $iID_Menu)

    ;
    ; Create all controls that will be common to all tabs
    ;
    GUICtrlCreateButton("Btn1", 10, 5, 50, 25)
    GUICtrlCreateButton("Btn2", 70, 5, 45, 25)
    GUICtrlCreateButton("Btn3", $mw - 55, 5, 40, 25)
    GUICtrlSetOnEvent(-1, "handle_Btn3")

    GUICtrlCreateButton("Exit", 10, $mh - 50, 45, 25)
    GUICtrlSetOnEvent(-1, "Event_GUIClose")

    GUICtrlCreateButton("Save", ($mw / 2), $mh - 50, 45, 25)
    GUICtrlCreateButton("Quit", $mw - 55, $mh - 50, 45, 25)

    create_tabs($mw, $mh) ; Create the tabbed interface

    ; Create a listview beside the Tabs
    createListView("X", 250, 60, 200, 200)

EndFunc   ;==>CreateAllControls

Func create_tabs($mw, $mh)
    $hTab = GUICtrlCreateTab(20, 35, $mw - 50, $mh - 90)
    createTabItem("Games")
    createTabItem("Payments")
    createTabItem("Items")
    _GUICtrlTab_ActivateTab($hTab, 0)
EndFunc   ;==>create_tabs

Func createTabItem($sTitle)
    Local $tabnum, $chu, $chl

    $tabnum = _GUICtrlTab_GetItemCount($hTab)
    _DebugOut("+++: $tabnum = " & $tabnum)
    $chu = StringLeft($sTitle, 1)
    $chl = StringLower($chu)
    GUICtrlCreateTabItem($sTitle & "-" & $chl)
    _GUICtrlTab_ActivateTab($hTab, $tabnum)

    createListView("T", 25, 60, 200, 200)

    GUICtrlCreateButton("TEST-" & $chu, 25, 260, 70, 20)
    GUICtrlCreateTabItem("")
EndFunc   ;==>createTabItem

Func createListView($type, $x, $y, $w, $h, $lnum = @ScriptLineNumber)
    #forceref $lnum
    _DebugOut("+++:" & $lnum & ": createListView(" & $type & ", " & $x & "," & $y & "," & $w & "," & $h & ") entered")
    Local $str, $flags, $id

    $str = "col1" & @TAB & "|col2" & @TAB & "|col3" & @TAB
    $flags = 0
    $flags = BitOR($flags, $WS_BORDER)
    $flags = BitOR($flags, $WS_VSCROLL)
    $flags = BitOR($flags, $WS_HSCROLL)
    $flags = BitOR($flags, $WS_TABSTOP)
    ;$flags = BitOR($flags, $LBS_NOTIFY)
    $flags = BitOR($flags, $LVS_SHOWSELALWAYS)

    $id = GUICtrlCreateListView($str, $x, $y, $w, $h)
    _ArrayAdd($aIDs, $id)
    _ArrayAdd($ahWnds, GUICtrlGetHandle($id))
    _ArrayAdd($aTypes, $type)
EndFunc   ;==>createListView

Func Event_GUIClose()
    Exit (1)
EndFunc   ;==>Event_GUIClose

Func handle_Btn3()
    Local $tabnum = _GUICtrlTab_GetCurSel($hTab) + 1
    If ($tabnum > 2) Then $tabnum = 0
    _GUICtrlTab_ActivateTab($hTab, $tabnum)
EndFunc   ;==>handle_Btn3

Func fillListViews()
    Local $ndx, $id, $hWnd, $cnt, $subndx, $iIndex, $str, $chu

    For $ndx = 1 To UBound($aIDs) - 1

        $id = $aIDs[$ndx]
        $hWnd = GUICtrlGetHandle($id)

        If ($aTypes[$ndx] == "T") Then
            $chu = StringLeft(_GUICtrlTab_GetItemText($hTab, $ndx - 1), 1)
        Else
            $chu = "X"

        EndIf

        For $cnt = 1 To 5
            $iIndex = _GUICtrlListView_AddItem($hWnd, "Item" & $ndx)
            For $subndx = 1 To 3
                $str = "Sub" & $cnt & $chu & $subndx
                _GUICtrlListView_AddSubItem($hWnd, $iIndex, $str, $subndx - 1)
            Next
        Next
    Next
EndFunc   ;==>fillListViews

 

Share this post


Link to post
Share on other sites



#2 ·  Posted (edited)

I think WM_COMMAND would actually get a message when a tab is selected. This works though

#include <guitab.au3>
#include <GuiConstants.au3>

Global $hGUI = GUICreate("Tab Blocking", 412, 280, 302, 218)
Global $tabTab = GUICtrlCreateTab(8, 8, 396, 256)
Global $idTab1 = GUICtrlCreateTabItem("Tab 1")
Global $chkBlock1 = GUICtrlCreateCheckbox("Block tab switching to 2 and 3", 20, 30, 200, 20)
Global $idTab2 = GUICtrlCreateTabItem("Tab 2")
Global $idTab3 = GUICtrlCreateTabItem("Tab 3")
Global $selected_tab = _GUICtrlTab_GetCurSel($tabTab)

GUISetState(@SW_SHOW, $hGUI)

While (True)
    Switch (GUIGetMsg())
        Case $GUI_EVENT_CLOSE
            GUIDelete($hGUI)
            Exit 0
        Case $tabTab
            If (GUICtrlRead($chkBlock1) = $GUI_CHECKED) Then
                _GUICtrlTab_SetCurFocus($tabTab, $selected_tab)
            Else
                $selected_tab = _GUICtrlTab_GetCurSel($tabTab)
            EndIf
    EndSwitch
WEnd

You'd probably need a Window proc in order to intercept the message to change tabs on your tab control before it is sent to your tab control.

Here are some constants defined in the TabConstants file that might help you

Global Const $TCN_FOCUSCHANGE = ($TCN_FIRST - 4)
Global Const $TCN_KEYDOWN = ($TCN_FIRST - 0)
Global Const $TCN_SELCHANGING = ($TCN_FIRST - 2)

I'll play with it later and see if there's another solution that prevents the tab from ever changing. The above code just sets the focus back to the original tab after the tab has actually changed. (Just looks like a flicker)

Edited by InunoTaishou

Share this post


Link to post
Share on other sites

I was wrong, WM_NOTIFY will let you block the command to change tab. Returning 1 in the WM_NOTIFY prevents the tab from ever changing.

#include <GUITab.au3>
#include <GuiConstants.au3>

Global $hGUI = GUICreate("Tab Blocking", 412, 280, 302, 218)
Global $tabTab = GUICtrlCreateTab(8, 8, 396, 256)
Global $idTab1 = GUICtrlCreateTabItem("Tab 1")
Global $chkBlock1 = GUICtrlCreateCheckbox("Block tab switching to 2 and 3", 20, 50, 200, 20)
Global $idTab2 = GUICtrlCreateTabItem("Tab 2")
Global $chkBlock2 = GUICtrlCreateCheckbox("Block tab switching to 1 and 3", 20, 50, 200, 20)
Global $idTab3 = GUICtrlCreateTabItem("Tab 3")
Global $chkBlock3 = GUICtrlCreateCheckbox("Block tab switching to 1 and 2", 20, 50, 200, 20)

GUIRegisterMsg($WM_NOTIFY, "WM_NOTIFY")

GUISetState(@SW_SHOW, $hGUI)

While (True)
    Switch (GUIGetMsg())
        Case $GUI_EVENT_CLOSE
            GUIDelete($hGUI)
            Exit 0
        Case $tabTab
            ConsoleWrite("Tab Clicked" & @LF)
    EndSwitch
WEnd

Func WM_NOTIFY($hWndFrom, $iMsg, $wParam, $lParam)
    #forceref $hWndFrom, $lParam
    Local $hWndStruct = DllStructCreate($tagNMHDR, $lParam)
    Local $iCode = DllStructGetData($hWndStruct, "Code")
    Local $idFrom = DllStructGetData($hWndStruct, "IDFrom")

    Switch ($hWndFrom)
        Case $hGUI
            Switch ($iCode)
                Case $TCN_SELCHANGING
                    Switch (_GUICtrlTab_GetCurSel($tabTab))
                        Case 0
                            If (GUICtrlRead($chkBlock1) = $GUI_CHECKED) Then Return 1
                        Case 1
                            If (GUICtrlRead($chkBlock2) = $GUI_CHECKED) Then Return 1
                        Case 2
                            If (GUICtrlRead($chkBlock3) = $GUI_CHECKED) Then Return 1
                    EndSwitch
            EndSwitch
    EndSwitch

    Return $GUI_RUNDEFMSG
EndFunc

 

Share this post


Link to post
Share on other sites

AndySO1,

I did it this way:

#include <GUIConstantsEx.au3>

Global $aTabs[5]

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

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

For $i = 0 To 4
    $aTabs[$i] = GUICtrlCreateTabItem("Tab " & $i)
Next
GUICtrlCreateTabItem("")

GUICtrlCreateLabel("Select tab to disable", 10, 230, 200, 20)
$cCombo = GUICtrlCreateCombo("", 10, 250, 200, 20)
GUICtrlSetData($cCombo, "0|1|2|3|4")

GUISetState()

$iCurrDisabledTab = -1
$iCurrTab = 0

While 1

    Switch GUIGetMsg()
        Case $GUI_EVENT_CLOSE
            Exit
        Case $cCombo
            $iDisableTab = GUICtrlRead($cCombo)
            If $iDisableTab <> $iCurrDisabledTab Then
                If $iCurrDisabledTab <> -1 Then
                    GUICtrlSetData($aTabs[$iCurrDisabledTab], "Tab " & $iCurrDisabledTab)
                EndIf
                GUICtrlSetData($aTabs[$iDisableTab], "Disabled")
                $iCurrDisabledTab = $iDisableTab
            EndIf
        Case $cTab
            $iSelTab = GUICtrlRead($cTab)
            If $iSelTab = $iCurrDisabledTab Then
                GUICtrlSetState($aTabs[$iCurrTab], $GUI_SHOW)
            Else
                $iCurrTab = $iSelTab
            EndIf

    EndSwitch

WEnd

M23


Any of my own code posted anywhere on the forum is available for use by others without any restriction of any kind._______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

 

Share this post


Link to post
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

  • Similar Content

    • MMcBrine
      By MMcBrine
      Hi all and thanks for stopping by to read this, much appreciated.
      What I have is a gui with a tab control that has 8 tabs, Some of those can have multiple pages that I would like to display in a "Sub" tab control which will display information from various sources (web Pages) .
      I have been looking around on the web, but have not stumbled on the source for information yet...
      Any help would be great,
      thanks
      Mike


    • gelmir
      By gelmir
      Hi, I have simple problem. I try create GUI with tabs and when I use in one tab IpAddressInputBox then this control is visible for all tabs when I switch view. I attached example of my problem. Could you advice me how to fix this issue? Ofc i can use standard input box but I want to stay with IpadressInputBox in tab.
       
      #include <ButtonConstants.au3> #include <EditConstants.au3> #include <GUIConstantsEx.au3> #include <GuiIPAddress.au3> #include <StaticConstants.au3> #include <TabConstants.au3> #include <WindowsConstants.au3> #Region ### START Koda GUI section ### Form=c:\users\root\desktop\tabs.kxf $Form1_1 = GUICreate("Form1", 623, 204, 192, 114) $Tab1 = GUICtrlCreateTab(80, 40, 457, 137) $TabSheet1 = GUICtrlCreateTabItem("TabSheet1") $TabSheet2 = GUICtrlCreateTabItem("TabSheet2") GUICtrlSetState(-1,$GUI_SHOW) $IPAddress1 = _GUICtrlIpAddress_Create($Form1_1, 400, 88, 105, 17) _GUICtrlIpAddress_Set($IPAddress1, "0.0.0.0") $Button1 = GUICtrlCreateButton("Button1", 256, 80, 113, 17) $Label1 = GUICtrlCreateLabel("Label1", 256, 104, 116, 17) $Edit1 = GUICtrlCreateEdit("", 96, 80, 145, 81) GUICtrlSetData(-1, "Edit1") $Input1 = GUICtrlCreateInput("Input1", 256, 128, 105, 21) GUICtrlCreateTabItem("") GUISetState(@SW_SHOW) #EndRegion ### END Koda GUI section ### While 1 $nMsg = GUIGetMsg() Switch $nMsg Case $GUI_EVENT_CLOSE Exit EndSwitch WEnd