Jump to content

How to prohibit switching Tabs on Tab control


AndyS01
 Share

Recommended Posts

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

 

Link to comment
Share on other sites

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

 

Link to comment
Share on other sites

  • Moderators

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

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

×
×
  • Create New...