Jump to content
Sign in to follow this  
Melba23

GUIDragTab - New version - 19 Jul 11

Recommended Posts

Melba23

New version - 19 Jul 11

Changes:

- Now works with UDF created tab structures as well as native ones.

- Changes to internal coding to prevent ghost flashes of the insert indicator when selecting new tabs. The indicator will now only appear when the active tab is clicked.

New UDF and new examples below. :)


A recent thread asked if it was possible to rearrange the order of the tab headers - with a bit of help from martin I produced some code to do this and here it is in UDF form - GUIDragTab.au3. ;)

A few points to note: ;)

- The user has to pass an array containing a fair amount of information to the UDF - however all of this is easy to obtain as you create the tab structure in your script

- All the controls within the tab structure must be placed on individual child GUIs which are hidden/shown as required - this is because the UDF actually renames the tab headers and keeps track of which GUI to display with what tab

- At present it only works with the native GUICtrlCreateTab/TabItem functions - I am working on a version which will also cope with the GUITab UDF created versions.

First an example which uses native AutoIt tabs MessageLoop mode:

#include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>

#include "GuiTabDrag.au3"

; [0][0] = Tab count     - [0][1] = GUI handle        - [0][2] = Tab ControlID    - [0][3] = Tab Handle
; [n][0] = TabItem title - [n][1] = TabItem ControlID - [n][2] = Child GUI handle
Global $aParameters[7][5] = [ _
    [6,            0, 0, 0, 0], _
    ["Tab_0",      0, 0, 0, 0], _
    ["Tab__1",     0, 0, 0, 0], _
    ["Tab___2",    0, 0, 0, 0], _
    ["Tab____3",   0, 0, 0, 0], _
    ["Tab_____4",  0, 0, 0, 0], _
    ["Tab______5", 0, 0, 0, 0]]

_Main()

Func _Main()

    ; Create GUI
    $hGUI = GUICreate("Test", 500, 500)
    $aParameters[0][1] = $hGUI

    ; Create Tab
    $hTab = GUICtrlCreateTab(5, 5, 390, 290)
    $aParameters[0][2] = $hTab
    $aParameters[0][3] = GUICtrlGetHandle($hTab)

    ; Create Tab items
    For $i = 1 To UBound($aParameters) - 1
        $aParameters[$i][1] = GUICtrlCreateTabItem($aParameters[$i][0])
    Next
    GUICtrlCreateTabItem("")

    $hDragger = GUICtrlCreateCheckbox(" Draggable Tabs", 10, 470, 150, 20)
    GUICtrlSetState(-1, $GUI_CHECKED)

    GUISetState(@SW_SHOW, $hGUI)

    ; Create child GUIs
    For $i = 1 To UBound($aParameters) - 1
        $aParameters[$i][2] = GUICreate($i, 350, 210, 20, 40, $WS_POPUP, $WS_EX_MDICHILD, $hGUI)
        GUISetBkColor(0xffffff)
        ; Add label to show which GUI is displayed
        GUICtrlCreateLabel($i - 1, 0, 0, 350, 210)
        GUICtrlSetFont(-1, 96)
        GUISetState(@SW_HIDE)
    Next

    ; Switch back to main GUI
    GUISwitch($hGUI)

    ; Initialise tab dragging, set tab 3 to show, and set indicator to green
    _GUIDragTab_Init($aParameters , 5, 0x00FF00)

    ; Destroy array to save memory
    $aParameters = 0

    While 1

        $iMsg = GUIGetMsg()
        Switch $iMsg
            Case $GUI_EVENT_CLOSE
                Exit
            Case $hTab
                ; Set correct GUI to display
                _GUIDragTab_Show()
            Case $hDragger
                ; Set or cancel dragging
                If GUICtrlRead($hDragger) = 1 Then
                    _GUIDragTab_Set(True)
                Else
                    _GUIDragTab_Set(False)
                EndIf
        EndSwitch

        ; Drag tabs
        _GUIDragTab_Action($iMsg)

    WEnd

EndFunc

And now native tabs in OnEvent mode:

#include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>

#include "GuiTabDrag.au3"

Opt("GUIOnEventMode", 1)

Global $hDragger

; [0][0] = Tab count     - [0][1] = GUI handle        - [0][2] = Tab ControlID    - [0][3] = Tab Handle
; [n][0] = TabItem title - [n][1] = TabItem ControlID - [n][2] = Child GUI handle
Global $aParameters[7][5] = [ _
    [6,            0, 0, 0, 0], _
    ["Tab_0",      0, 0, 0, 0], _
    ["Tab__1",     0, 0, 0, 0], _
    ["Tab___2",    0, 0, 0, 0], _
    ["Tab____3",   0, 0, 0, 0], _
    ["Tab_____4",  0, 0, 0, 0], _
    ["Tab______5", 0, 0, 0, 0]]

_Main()

Func _Main()

    ; Create GUI
    $hGUI = GUICreate("Test", 500, 500)
    GUISetOnEvent($GUI_EVENT_CLOSE, "_Exit")
    $aParameters[0][1] = $hGUI

    ; Create tab
    $hTab = GUICtrlCreateTab(5, 5, 390, 290)
    GUICtrlSetOnEvent(-1, "_Tab_Clicked")
    $aParameters[0][2] = $hTab
    $aParameters[0][3] = GUICtrlGetHandle($hTab)

    ; Create Tab items
    For $i = 1 To UBound($aParameters) - 1
        $aParameters[$i][1] = GUICtrlCreateTabItem($aParameters[$i][0])
    Next
    GUICtrlCreateTabItem("")

    $hDragger = GUICtrlCreateCheckbox(" Draggable Tabs", 10, 470, 150, 20)
    GUICtrlSetState(-1, $GUI_CHECKED)
    GUICtrlSetOnEvent(-1, "_Drag_Set")

    GUISetState(@SW_SHOW, $hGUI)

    ; Register $GUI_EVENT_PRIMARYDOWN event to UDF function
    _GUIDragTab_SetOnEvent()

    ; Create child GUIs
    For $i = 1 To UBound($aParameters) - 1
        $aParameters[$i][2] = GUICreate($i, 350, 210, 20, 40, $WS_POPUP, $WS_EX_MDICHILD, $hGUI)
        GUISetBkColor(0xffffff)
        ; Add label to show which GUI is displayed
        GUICtrlCreateLabel($i - 1, 0, 0, 350, 210)
        GUICtrlSetFont(-1, 96)
        GUISetState(@SW_HIDE)
    Next

    ; Switch back to main GUI
    GUISwitch($hGUI)

    ; Initialise tab dragging and set tab 3 to show
    _GUIDragTab_Init($aParameters, 3)

    ; Destroy array to save memory
    $aParameters = 0

    While 1
        Sleep(10)
    WEnd

EndFunc

Func _Drag_Set()
    ; Set or cancel dragging
    If GUICtrlRead($hDragger) = 1 Then
        _GUIDragTab_Set(True)
    Else
        _GUIDragTab_Set(False)
    EndIf
EndFunc

Func _Tab_Clicked()
    _GUIDragTab_Show()
EndFunc

Func _Exit()
    Exit
EndFunc

[New] Here are UDF created tabs in MessageLoop mode:

#include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>

#include "GuiTabDrag.au3"

; [0][0] = Tab count     - [0][1] = GUI handle        - [0][2] = Tab ControlID    - [0][3] = Tab Handle
; [n][0] = TabItem title - [n][1] = TabItem ControlID - [n][2] = Child GUI handle
Global $aParameters[7][5] = [ _
    [6,            0, 0, 0, 0], _
    ["Tab_0",      0, 0, 0, 0], _
    ["Tab__1",     0, 0, 0, 0], _
    ["Tab___2",    0, 0, 0, 0], _
    ["Tab____3",   0, 0, 0, 0], _
    ["Tab_____4",  0, 0, 0, 0], _
    ["Tab______5", 0, 0, 0, 0]]

_Main()

Func _Main()

    ; Create GUI
    $hGUI = GUICreate("Test", 500, 500)
    $aParameters[0][1] = $hGUI

    ; Create Tab
    $hTab = _GUICtrlTab_Create($hGUI, 5, 5, 390, 290)
    $aParameters[0][3] = $hTab ; Ensure $aParameters[0][2] remains 0 to indicate UDF Tab structure

    ; Create Tab items
    For $i = 1 To UBound($aParameters) - 1
        $aParameters[$i][1] = _GUICtrlTab_InsertItem($hTab, $i - 1 , $aParameters[$i][0])
    Next
    GUICtrlCreateTabItem("")

    $hDragger = GUICtrlCreateCheckbox(" Draggable Tabs", 10, 470, 150, 20)
    GUICtrlSetState(-1, $GUI_CHECKED)

    GUISetState(@SW_SHOW, $hGUI)

    ; Create child GUIs
    For $i = 1 To UBound($aParameters) - 1
        $aParameters[$i][2] = GUICreate($i, 350, 210, 20, 40, $WS_POPUP, $WS_EX_MDICHILD, $hGUI)
        GUISetBkColor(0xffffff)
        ; Add label to show which GUI is displayed
        GUICtrlCreateLabel($i - 1, 0, 0, 350, 210)
        GUICtrlSetFont(-1, 96)
        GUISetState(@SW_HIDE)
    Next

    ; Switch back to main GUI
    GUISwitch($hGUI)

    ; Initialise tab dragging, set tab 3 to show, and set indicator to green
    _GUIDragTab_Init($aParameters , 5, 0x00FF00)

    ; Destroy array to save memory
    $aParameters = 0

    ; Register WM_NOTIFY to detect tab clicks
    _GUIDragTab_NOTIFY_Reg()

    While 1

        $iMsg = GUIGetMsg()
        Switch $iMsg
            Case $GUI_EVENT_CLOSE
                Exit
            Case $hDragger
                ; Set or cancel dragging
                If GUICtrlRead($hDragger) = 1 Then
                    _GUIDragTab_Set(True)
                Else
                    _GUIDragTab_Set(False)
                EndIf
        EndSwitch

        ; Drag tabs
        _GUIDragTab_Action($iMsg)

    WEnd

EndFunc

[New] And now UDF tabs in OnEvent mode:

#include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>

#include "GuiTabDrag.au3"

Opt("GUIOnEventMode", 1)

Global $hDragger

; [0][0] = Tab count     - [0][1] = GUI handle        - [0][2] = Tab ControlID    - [0][3] = Tab Handle
; [n][0] = TabItem title - [n][1] = TabItem ControlID - [n][2] = Child GUI handle
Global $aParameters[7][5] = [ _
    [6,            0, 0, 0, 0], _
    ["Tab_0",      0, 0, 0, 0], _
    ["Tab__1",     0, 0, 0, 0], _
    ["Tab___2",    0, 0, 0, 0], _
    ["Tab____3",   0, 0, 0, 0], _
    ["Tab_____4",  0, 0, 0, 0], _
    ["Tab______5", 0, 0, 0, 0]]

_Main()

Func _Main()

    ; Create GUI
    $hGUI = GUICreate("Test", 500, 500)
    GUISetOnEvent($GUI_EVENT_CLOSE, "_Exit")
    $aParameters[0][1] = $hGUI

    ; Create Tab
    $hTab = _GUICtrlTab_Create($hGUI, 5, 5, 390, 290)
    $aParameters[0][3] = $hTab ; Ensure $aParameters[0][2] remains 0 to indicate UDF Tab structure

    ; Create Tab items
    For $i = 1 To UBound($aParameters) - 1
        $aParameters[$i][1] = _GUICtrlTab_InsertItem($hTab, $i - 1 , $aParameters[$i][0])
    Next
    GUICtrlCreateTabItem("")

    ; Create Tab items
    For $i = 1 To UBound($aParameters) - 1
        $aParameters[$i][1] = GUICtrlCreateTabItem($aParameters[$i][0])
    Next
    GUICtrlCreateTabItem("")

    $hDragger = GUICtrlCreateCheckbox(" Draggable Tabs", 10, 470, 150, 20)
    GUICtrlSetState(-1, $GUI_CHECKED)
    GUICtrlSetOnEvent(-1, "_Drag_Set")

    GUISetState(@SW_SHOW, $hGUI)

    ; Register $GUI_EVENT_PRIMARYDOWN event to UDF function
    _GUIDragTab_SetOnEvent()

    ; Create child GUIs
    For $i = 1 To UBound($aParameters) - 1
        $aParameters[$i][2] = GUICreate($i, 350, 210, 20, 40, $WS_POPUP, $WS_EX_MDICHILD, $hGUI)
        GUISetBkColor(0xffffff)
        ; Add label to show which GUI is displayed
        GUICtrlCreateLabel($i - 1, 0, 0, 350, 210)
        GUICtrlSetFont(-1, 96)
        GUISetState(@SW_HIDE)
    Next

    ; Switch back to main GUI
    GUISwitch($hGUI)

    ; Initialise tab dragging and set tab 3 to show
    _GUIDragTab_Init($aParameters, 3)

    ; Destroy array to save memory
    $aParameters = 0

    ; Register WM_NOTIFY to detect tab clicks
    _GUIDragTab_NOTIFY_Reg()

    While 1
        Sleep(10)
    WEnd

EndFunc

Func _Drag_Set()
    ; Set or cancel dragging
    If GUICtrlRead($hDragger) = 1 Then
        _GUIDragTab_Set(True)
    Else
        _GUIDragTab_Set(False)
    EndIf
EndFunc

Func _Tab_Clicked()
    _GUIDragTab_Show()
EndFunc

Func _Exit()
    Exit
EndFunc

[New] And finally the UDF itself:

#include-once

; #INDEX# ============================================================================================================
; Title .........: GUIDragTab
; AutoIt Version : v3.3 or higher
; Language ......: English
; Description ...: Allows switchable dragging of native Autoit tab item headers
; Remarks .......: All controls for the tabitems must be created within child GUIs.
;                  The user must create an array holding details of the tab structure as set out below
;                  and pass it to the UDF when initialising
; Note ..........:
; Author(s) .....: Melba23 - thanks to martin for the original idea and the label display code lines
; ====================================================================================================================

; Array to pass to the UDF:
; Dimensioned: [Number of tabitems + 1][3]
; Elements set as follows
; [0][0] = No of Tabs      - [0][1] = GUI handle          - [0][2] = Tab ControlID       - [0][3] = Tab Handle
; [n][0] = TabItem n title - [n][1] = TabItem n ControlID - [n][2] = Handle of child GUI holding controls for tabitem n
; ====================================================================================================================

;#AutoIt3Wrapper_Au3Check_Parameters=-d -w 1 -w 2 -w 3 -w 4 -w 5 -w 6
;Opt("MustDeclareVars", 1)

; #INCLUDES# =========================================================================================================
#include <GuiTab.au3>

; #GLOBAL VARIABLES# =================================================================================================
; Copy of parameter array passed with _GUIDragTab_Init
Global $aGDT_Tab_Parameters
; Array holding coords of tab header block
Global $aGDT_Tab_Block[4]
; Array : [0] = Last Indic position - [1] = Last displayed GUI index - [2] = Indic colour - [3] = Draggable flag
Global $aGDT_UDF_Info[4] = [-1, -1, 0xFF0000, False]

; #CURRENT# ==========================================================================================================
; _GUIDragTab_Init:           Initialises the GUI containing the tab structure
; _GUIDragTab_SetOnEvent:     Register drag function for OnEvent mode
; _GUIDragTab_Show:           Displays the correct child GUI for the selected tab
; _GUIDragTab_Action:         Drags the tab (MessageLoop mode only)
; _GUIDragTab_Set:            Toggles draggable state
; _GUIDragTab_NOTIFY_Reg:     Register WM_NOTIFY handler for use with UDF created Tab structures
; _GUIDragTab_NOTIFY_Handler: Handler for WM_NOTIFY messages
; ====================================================================================================================

; #INTERNAL_USE_ONLY#=================================================================================================
; _GUIDragTab_Action_Event:   OnEvent mode function to drag tab
; _GUIDragTab_Reset_Tabs:     Rename tabs to required order
; _GUIDragTab_Get_Tab_Coords: Store coordinates of current tab structure
; ====================================================================================================================

; #FUNCTION# =========================================================================================================
; Name...........: _GUIDragTab_Init
; Description ...: Initialises the GUI containing the tab structure
; Syntax.........: _GUIDragTab_Init($aParameters[, $iSet = 0[, $iColour = 0xFF0000]])
; Parameters ....: $aParameters - Array containing details of the tab structure
;                  $iSet        - (Optional) Tab to be displayed intially - default = 0
;                  $iColour     - (Optional) Colour for the tab position indicator (default = 0xFF0000)
; Requirement(s).: v3.3 +
; Return values .: Success:  Returns 1
;                  Failure:  Returns 0 and sets @error as follows:
;                  1 = $aParameters is not an array
; Author ........: Melba23
; Remarks .......: This function should be called once the $aParameters array has been created with the required data
;                  Only one GUI can be initialised at any one time.
; Example........: Yes
;=====================================================================================================================
Func _GUIDragTab_Init($aParameters, $iSet = 0, $iColour = 0xFF0000)

    ; Check and copy passed array
    If Not IsArray($aParameters) Then
        Return SetError(1, 0, 0)
    EndIf
    $aGDT_Tab_Parameters = $aParameters
    ; Set initial tab positions into array
    For $i = 1 To $aGDT_Tab_Parameters[0][0]
        $aGDT_Tab_Parameters[$i][3] = $i - 1
    Next
    ; Get coordinates of tab block and the inter-tab positions
    _GUIDragTab_Get_Tab_Coords()
    ; Check validity of required tab and show - default to 0
    If $iSet > $aGDT_Tab_Parameters[0][0] Then
        $iSet = 0
    EndIf
    _GUIDragTab_Show($iSet)
    ; Set required colour for the indicator
    $aGDT_UDF_Info[2] = $iColour
    ; Set draggable flag
    $aGDT_UDF_Info[3] = True

    Return 1

EndFunc   ;==>_GUIDragTab_Init

; #FUNCTION# =========================================================================================================
; Name...........: _GUIDragTab_SetOnEvent
; Description ...: Register drag function for OnEvent mode
; Syntax.........: _GUIDragTab_SetOnEvent()
; Parameters ....: None
; Requirement(s).: v3.3 +
; Return values .: None
; Author ........: Melba23
; Remarks .......: If a $GUI_EVENT_PRIMARYDOWN event function already exists call the _GUIDragTab_Action_Event
;                  function from within it to prevent overwriting
; Example........: Yes
;=====================================================================================================================
Func _GUIDragTab_SetOnEvent()

    ; Register drag function for OnEvent mode
    GUISetOnEvent(-7, "_GUIDragTab_Action_Event") ; $GUI_EVENT_PRIMARYDOWN

EndFunc   ;==>_GUIDragTab__SetOnEvent

; #FUNCTION# =========================================================================================================
; Name...........: _GUIDragTab_Show
; Description ...: Displays the correct child GUI and sets focus for the selected tab
; Syntax.........: _GUIDragTab_Show($iSet = -1)
; Parameters ....: $iSet - Tab to get focus and display child GUI
; Requirement(s).: v3.3 +
; Return values .: None
; Author ........: Melba23
; Remarks .......:
; Example........: Yes
;=====================================================================================================================
Func _GUIDragTab_Show($iSet = -1)

    Local $iGUI

    ; Determine correct GUI to show
    If $iSet <> -1 Then
        ; Native Tab structure
        $iGUI = $aGDT_Tab_Parameters[$iSet + 1][3]
    Else
        ; UDF Tab structure
        $iGUI = $aGDT_Tab_Parameters[GUICtrlRead($aGDT_Tab_Parameters[0][2]) + 1][3]
    EndIf
    ; If the GUI has changed
    If $aGDT_UDF_Info[1] <> $iGUI Then
        WinSetState($aGDT_Tab_Parameters[$iGUI + 1][2], "", @SW_SHOW)
        If $aGDT_UDF_Info[1] <> -1 Then
            WinSetState($aGDT_Tab_Parameters[$aGDT_UDF_Info[1] + 1][2], "", @SW_HIDE)
        EndIf
        $aGDT_UDF_Info[1] = $iGUI
    EndIf
    ; Set focus to displayed tab
    If $aGDT_Tab_Parameters[0][2] Then
        ; Native Tab structure
        GUICtrlSetState($aGDT_Tab_Parameters[$iSet + 1][1], 16) ; $GUI_SHOW
    Else
        ; UDF Tab structure
        _GUICtrlTab_SetCurSel($aGDT_Tab_Parameters[0][3], $iSet)
        _GUICtrlTab_SetCurFocus($aGDT_Tab_Parameters[0][3], $iSet)
    EndIf

EndFunc   ;==>_GUIDragTab_Show

; #FUNCTION# =========================================================================================================
; Name...........: _GUIDragTab_Action
; Description ...: Drags the tab (MessageLoop mode only)
; Syntax.........: _GUIDragTab_Action($iMsg)
; Parameters ....: $iMsg - Return value from GUIGetMsg
; Requirement(s).: v3.3 +
; Return values .: None
; Author ........: Melba23 - thanks to martin for the label display code
; Remarks .......: This function should only be called in MessageLoop mode.  OnEvent mode uses an internal function
;                  set by _GUIDragTab_Init
; Example........: Yes
;=====================================================================================================================
Func _GUIDragTab_Action($iMsg)

    Local $iDivider_X, $iCurr_Tab

    ; Check if correct message and tabs are draggable
    If $iMsg <> -7 Or $aGDT_UDF_Info[3] = False Then ; $GUI_EVENT_PRIMARYDOWN
        Return
    Else
        ; Get cursor position
        Local $aCInfo = GUIGetCursorInfo($aGDT_Tab_Parameters[0][1])
        If $aCInfo[4] = $aGDT_Tab_Parameters[0][2] Then
            ; Return if not over the tab block
            If $aCInfo[0] < $aGDT_Tab_Block[0] Or $aCInfo[0] > $aGDT_Tab_Block[2] Or $aCInfo[1] < $aGDT_Tab_Block[1] Or $aCInfo[1] > $aGDT_Tab_Block[3] Then
                Return
            Else
                ; Get mouse position
                $aCInfo = GUIGetCursorInfo($aGDT_Tab_Parameters[0][1])
                ; Get current tab
                If $aGDT_Tab_Parameters[0][2] Then
                    ; Native Tab structure
                    $iCurr_Tab = GUICtrlRead($aGDT_Tab_Parameters[0][2])
                Else
                    ; UDF Tab structure
                    $iCurr_Tab = _GUICtrlTab_GetCurSel($aGDT_Tab_Parameters[0][3])
                EndIf
                ; Check if current tab by comparing current GUI displayed and current real tab selection
                If $aGDT_UDF_Info[1] <> $aGDT_Tab_Parameters[$iCurr_Tab + 1][3] Then
                    Return
                EndIf
                ; Switch to main GUI
                Local $hOldGUI = GUISwitch($aGDT_Tab_Parameters[0][1])
                ; Create the label to indicate the new tab position
                Local $hLabel = GUICtrlCreateLabel("", 0, 0, 4, 18)
                Local $hLabel_Handle = GUICtrlGetHandle($hLabel)
                GUICtrlSetBkColor(-1, $aGDT_UDF_Info[2])
                GUICtrlSetState(-1, 32) ; $GUI_HIDE
                ; Switch back
                GUISwitch($hOldGUI)
                ; Switch to MessageLoop Mode
                Local $iOldOpt = Opt("GUIOnEventMode", 0)
                ; Allow drag position indication
                While 1
                    ; Get mouse position
                    $aCInfo = GUIGetCursorInfo($aGDT_Tab_Parameters[0][1])
                    ; If it is over the tab block
                    If $aCInfo[0] > $aGDT_Tab_Block[0] - 5 And $aCInfo[0] < $aGDT_Tab_Block[2] + 10 And $aCInfo[1] > $aGDT_Tab_Block[1] And $aCInfo[1] < $aGDT_Tab_Block[3] Then
                        ; Set divider postion based on mouse position
                        If $aCInfo[0] > $aGDT_Tab_Parameters[$aGDT_Tab_Parameters[0][0]][4] Then
                            ; Past right end
                            $iDivider_X = $aGDT_Tab_Block[2]
                        ElseIf $aCInfo[0] < $aGDT_Tab_Parameters[1][4] Then
                            ; Over first tab
                            $iDivider_X = 0
                        Else
                            ; Compare to tab positions to position indicator
                            For $i = $aGDT_Tab_Parameters[0][0] - 1 To 1 Step -1
                                If $aCInfo[0] > $aGDT_Tab_Parameters[$i][4] Then
                                    $iDivider_X = $aGDT_Tab_Parameters[$i][4]
                                    ExitLoop
                                EndIf
                            Next
                        EndIf
                        ; If the position has changed or if the mouse is close to the boundary
                        If $iDivider_X <> $aGDT_UDF_Info[0] Or $aCInfo[0] < $iDivider_X + 7 Then
                            ; Move the indicator
                            GUICtrlSetPos($hLabel, $iDivider_X + 3, $aGDT_Tab_Block[1] + 5)
                            ; Force label to show - needed as when the tab changes focus it hides the label
                            DllCall("user32.dll", "bool", "SetWindowPos", "hwnd", $hLabel_Handle, "hwnd", 0, "int", 0, "int", 0, "int", 0, "int", 0, "uint", 0x0043)
                            ; Second hwnd = $HWND_TOP, 0x0043 = BitOR($SWP_SHOWWINDOW, $SWP_NOSIZE, $SWP_NOMOVE)
                        EndIf
                        ; Store current label position
                        $aGDT_UDF_Info[0] = $iDivider_X
                    EndIf
                    ; Wait until the mouse button is released
                    If GUIGetMsg() = -8 Then ExitLoop ; $GUI_EVENT_PRIMARYUP
                WEnd
                ; Switch back to previous mode
                Opt("GUIOnEventMode", $iOldOpt)
                ; Delete label
                GUICtrlDelete($hLabel)
                ; Check mouse was over the tab block in Y coords
                If $aCInfo[1] > $aGDT_Tab_Block[1] And $aCInfo[1] < $aGDT_Tab_Block[3] Then
                    ; See which intertab position to use
                    For $i = $aGDT_Tab_Parameters[0][0] To 0 Step -1
                        If $aGDT_UDF_Info[0] = $aGDT_Tab_Parameters[$i][4] Then
                            _GUIDragTab_Reset_Tabs($iCurr_Tab, $i)
                            ExitLoop
                        EndIf
                    Next
                    ; Reset the tab edge coordinates as the reordered tabs could be of different sizes
                    _GUIDragTab_Get_Tab_Coords()
                EndIf
            EndIf
        EndIf
    EndIf

EndFunc   ;==>_GUIDragTab_Action

; #FUNCTION# =========================================================================================================
; Name...........: _GUIDragTab_Set
; Description ...: Toggles draggable state
; Syntax.........: _GUIDragTab_Set($fSetting = True)
; Parameters ....: $fSetting - Whether dragging is permitted
; Requirement(s).: v3.3 +
; Return values .: None
; Author ........: Melba23
; Remarks .......:
; Example........: Yes
;=====================================================================================================================
Func _GUIDragTab_Set($fSetting = True)

    ; Set or clear draggable flag
    If $fSetting Then
        $aGDT_UDF_Info[3] = True
    Else
        $aGDT_UDF_Info[3] = False
    EndIf

EndFunc

; #FUNCTION# =========================================================================================================
; Name...........: _GUIDragTab_NOTIFY_Reg
; Description ...: Register WM_NOTIFY handler for use with UDF created Tab structures
; Syntax.........: _GUIDragTab_NOTIFY_Reg()
; Parameters ....: None
; Requirement(s).: v3.3 +
; Return values .: None
; Author ........: Melba23
; Remarks .......: Only required for UDF created Tab structures.  If there is an existing WM_NOTIFY handler call
;                  _GUIDragTab_NOTIFY_Handler from within it and do not use this function
; Example........: Yes
;=====================================================================================================================
Func _GUIDragTab_NOTIFY_Reg()

    GUIRegisterMsg(0x004E, "_GUIDragTab_NOTIFY_Handler") ; $WM_NOTIFY

EndFunc   ;==> _GUIDragTab_NOTIFY_Reg

; #FUNCTION# =========================================================================================================
; Name...........: _GUIDragTab_NOTIFY_Handler
; Description ...: Handler for WM_NOTIFY messages
; Syntax.........: _GUIDragTab_NOTIFY_Handler()
; Parameters ....: None
; Requirement(s).: v3.3 +
; Return values .: None
; Author ........: Melba23
; Remarks .......: Call within an existing WM_NOTIFY handler rather than registering with _GUIDragTab_NOTIFY_Reg
; Example........: Yes
;=====================================================================================================================
Func _GUIDragTab_NOTIFY_Handler($hWnd, $iMsg, $wParam, $lParam)

    #forceref $hWnd, $iMsg, $wParam

    Local $tNMHDR = DllStructCreate("hwnd hWndFrom;uint_ptr IDFrom;INT Code", $lParam)
    If DllStructGetData($tNMHDR, "hWndFrom") = $aGDT_Tab_Parameters[0][3] And DllStructGetData($tNMHDR, "Code") = -2 Then
        _GUIDragTab_Show(_GUICtrlTab_GetCurSel( $aGDT_Tab_Parameters[0][3]))
    EndIf

EndFunc   ;==>_GUIDragTab_NOTIFY_Handler

; #INTERNAL_USE_ONLY#============================================================================================================
; Name...........: _GUIDragTab_Action_Event
; Description ...: OnEvent mode function to drag tab - sends $GUI_EVENT_PRIMARYDOWN message value to the function
; Author ........: Melba23
; Modified.......:
; Remarks .......: This function is used internally by _GUIDragTab in OnEvent mode to call _GUIDragTab_Action and drag tabs
; ===============================================================================================================================
Func _GUIDragTab_Action_Event()

    _GUIDragTab_Action(-7) ; $GUI_EVENT_PRIMARYDOWN

EndFunc   ;==>_GUIDragTab_Action_Event

; #INTERNAL_USE_ONLY#============================================================================================================
; Name...........: _GUIDragTab_Reset_Tabs
; Description ...: Rename tabs to required order
; Author ........: Melba23
; Modified.......:
; Remarks .......:
; ===============================================================================================================================
Func _GUIDragTab_Reset_Tabs($iCurrTab, $iDropTab)

    ; Do nothing if tab moved to same place (on itself or next up)
    Switch $iCurrTab
        Case $iDropTab - 1 To $iDropTab
            Return
    EndSwitch
    ; Which real tab is moving
    Local $iMoving_Tab = $aGDT_Tab_Parameters[$iCurrTab + 1][3]

    ; Reset order of real tabs
    If $iDropTab < $iCurrTab Then
        ; Move tabs down
        For $i = $iCurrTab To $iDropTab + 1 Step -1
            $aGDT_Tab_Parameters[$i + 1][3] = $aGDT_Tab_Parameters[$i][3]
        Next
        ; Insert current
        $aGDT_Tab_Parameters[$iDropTab + 1][3] = $iMoving_Tab
        ; Set focus to moved tab
        If $aGDT_Tab_Parameters[0][2] Then
            ; Native Tab structure
            GUICtrlSetState($aGDT_Tab_Parameters[$iDropTab + 1][1], 16) ; $GUI_SHOW
        Else
            ; UDF Tab structure
            _GUICtrlTab_SetCurSel($aGDT_Tab_Parameters[0][3], $iDropTab)
            _GUICtrlTab_SetCurFocus($aGDT_Tab_Parameters[0][3], $iDropTab)
        EndIf
    Else
        ; Move tabs up
        For $i = $iCurrTab To $iDropTab - 2
            $aGDT_Tab_Parameters[$i + 1][3] = $aGDT_Tab_Parameters[$i + 2][3]
        Next
        ; Insert current
        $aGDT_Tab_Parameters[$iDropTab][3] = $iMoving_Tab
        ; Set focus to moved tab
        If $aGDT_Tab_Parameters[0][2] Then
            ; Native Tab structure
            GUICtrlSetState($aGDT_Tab_Parameters[$iDropTab][1], 16) ; $GUI_SHOW
        Else
            ; UDF Tab structure
            _GUICtrlTab_SetCurSel($aGDT_Tab_Parameters[0][3], $iDropTab -1 )
            _GUICtrlTab_SetCurFocus($aGDT_Tab_Parameters[0][3], $iDropTab - 1)
        EndIf
    EndIf

    ; Rename tabs
    For $i = 1 To $aGDT_Tab_Parameters[0][0]
        If $aGDT_Tab_Parameters[0][2] Then
            ; Native Tab structure
            GUICtrlSetData($aGDT_Tab_Parameters[$i][1], $aGDT_Tab_Parameters[$aGDT_Tab_Parameters[$i][3] + 1][0])
        Else
            ; UDF Tab structure
            _GUICtrlTab_SetItemText($aGDT_Tab_Parameters[0][3], $i - 1, $aGDT_Tab_Parameters[$aGDT_Tab_Parameters[$i][3] + 1][0])
        EndIf
    Next

EndFunc   ;==>_GUIDragTab_Reset_Tabs

; #INTERNAL_USE_ONLY#============================================================================================================
; Name...........: _GUIDragTab_Get_Tab_Coords
; Description ...: Store coordinates of current tab structure
; Author ........: Melba23
; Modified.......:
; Remarks .......:
; ===============================================================================================================================
Func _GUIDragTab_Get_Tab_Coords()

    ; Get coords of tab rectangles
    For $i = $aGDT_Tab_Parameters[0][0] To 1 Step -1
        $aGDT_Tab_Block = _GUICtrlTab_GetItemRect($aGDT_Tab_Parameters[0][3], $i - 1)
        ; Set coords for intertab joins
        $aGDT_Tab_Parameters[$i][4] = $aGDT_Tab_Block[2]
    Next
    ; Amend rightmost edge to get tab block size
    $aGDT_Tab_Block[2] = $aGDT_Tab_Parameters[$aGDT_Tab_Parameters[0][0]][4]

EndFunc   ;==>_GUIDragTab_Get_Tab_Coords

[New] And a zip with all 5GUITabDrag.zip files:

I hope someone finds it of use. As usual, happy to get constructive criticism or (preferably) appreciative applause! :D

M23

Edited by Melba23

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
Andreik

Very nice example Melba23. Thanks for share. :)


When the words fail... music speaks

Share this post


Link to post
Share on other sites
Mikeman27294

Very interesting. Thanks for showing us that.

Share this post


Link to post
Share on other sites
Melba23

New version - 19 Jul 11

Changes:

- Now works with UDF created tab structures as well as native ones.

- Changes to internal coding to prevent ghost flashes of the insert indicator when selecting new tabs. The indicator will now only appear when the active tab is clicked.

New UDF and examples in first post. :)

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
Beege

Nice UDF Melba23. Very well commented too as usual! Posted Image

Share this post


Link to post
Share on other sites
powerofos

:)

Thanks M23.

Kim.Y

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
Sign in to follow this  

×