Jump to content

Checkbox Tree Question


cvocvo
 Share

Recommended Posts

I'm working with a checkbox tree and I'm having problems.

When I check the Parent checkbox (drive c or drive d in this case) then it checks all of the boxes. When I uncheck the Parent checkbox then it unchecks all of the child boxes. So that works great.

The problems lies in when I click a child checkbox. I want the child checkbox to only check that one, but it checks all of them including the parent. I also want when the parent is checked and all children are checked, if I click one of the children, I want it to uncheck the parent. Hopefully someone understand this checkbox tree stuff better than I do.

Code Snippet:

Func ChooseFixes()
$FormPassFail = GUICreate("Fix Drive: Options", 500, 350, 334, 140, $DS_MODALFRAME)
Local $iStyle = BitOR($TVS_EDITLABELS, $TVS_HASBUTTONS, $TVS_HASLINES, $TVS_LINESATROOT, $TVS_DISABLEDRAGDROP, $TVS_SHOWSELALWAYS, $TVS_CHECKBOXES)
Local $idTreeView = GUICtrlCreateTreeView(0, 0, 495, 200, $iStyle, $WS_EX_CLIENTEDGE)
Global $hTreeView = GUICtrlGetHandle($idTreeView), $Bad
_GUICtrlTreeView_BeginUpdate($hTreeView)
$NextButtonChooseFix = GUICtrlCreateButton("Next", 376, 265, 105, 49, 0)
GUICtrlSetOnEvent($NextButtonChooseFix, "NextButtonChooseFixClick")
$Bad = 0
;$OSVersion = "XP"
;$DState = "Bad"
;$EState = "Bad"
;$CState = "Good"
If $DState = "Bad" Then
    Local $idParent1 = GUICtrlCreateTreeViewItem('Drive D', $idTreeView)
    GUICtrlSetOnEvent($idParent1, "DriveDAllClick")
    Local $hParent1 = GUICtrlGetHandle($idParent1)
    $idLevel2P1 = GUICtrlCreateTreeViewItem('Make Drive Letter D:\ Available for Use', $idParent1)
    GUICtrlSetOnEvent($idLevel2P1, "DriveDAvailClick")
    $idLevel3P1 = GUICtrlCreateTreeViewItem('Install RamDisk on Drive D', $idParent1)
    GUICtrlSetOnEvent($idLevel3P1, "DriveDRamdiskClick")
    If $OSVersion = "7" Then
        $idLevel4P1 = GUICtrlCreateTreeViewItem('Make New Partition from Another Drive [*If RamDisk is checked it will nullify this checkbox*]', $idParent1)
        GUICtrlSetOnEvent($idLevel4P1, "DriveDPartitionclick")
    EndIf
    _GUICtrlTreeView_SetState($hTreeView, $hParent1, $TVIS_EXPANDED)
EndIf
If $EState = "Bad" Then
    Local $idParent2 = GUICtrlCreateTreeViewItem('Drive E', $idTreeView)
    GUICtrlSetOnEvent($idParent2, "DriveEAll")
    Local $hParent2 = GUICtrlGetHandle($idParent2)
    $idLevel2P2 = GUICtrlCreateTreeViewItem('Make Drive Letter E:\ Available for Use', $idParent2)
    GUICtrlSetOnEvent($idLevel2P2, "DriveEAvailClick")
    If $OSVersion = "7" Then
        $idLevel3P2 = GUICtrlCreateTreeViewItem('Make New Partition from Another Drive' & @CRLF & '[*If RamDisk is checked it will nullify this checkbox*]', $idParent2)
        GUICtrlSetOnEvent($idLevel3P2, "DriveEPartitionclick")
    EndIf
    _GUICtrlTreeView_SetState($hTreeView, $hParent2, $TVIS_EXPANDED)
EndIf

If $OSVersion = "7" Then
    GUICtrlCreateLabel("If 'Make a New Partition from Another Drive' was selected above, select a drive to take space from.", 10, 210, 495, 20)
    If $CState = "Good" Then
        $radioC = GUICtrlCreateRadio("Drive C", 10, 225, 60, 20)
        GUICtrlSetOnEvent($radioC, "RadioCClick")
        $FreeCSpace = Round(DriveSpaceFree("C:\"), 0)
        $TotalCSpace = Round(DriveSpaceTotal("C:\"), 0)
        $PercentCFree = $FreeCSpace * 100 / $TotalCSpace
        $PercentCFree = Round($PercentCFree, 1) & "%)"
        GUICtrlCreateLabel("(" & $FreeCSpace & " of " & $TotalCSpace & "MB Free " & $PercentCFree, 75, 228, 350, 20)
    EndIf
    If $DState = "Good" Then
        $type = DriveGetType("D:\")
            If $type = "Fixed" Then
                $radioD = GUICtrlCreateRadio("Drive D", 10, 245, 120, 20)
                GUICtrlSetOnEvent($radioD, "RadioDClick")
                $FreeDSpace = Round(DriveSpaceFree("D:\"), 0)
                $TotalDSpace = Round(DriveSpaceTotal("D:\"), 0)
                $PercentDFree = $FreeDSpace * 100 / $TotalDSpace
                $PercentDFree = Round($PercentDFree, 1) & "%)"
                GUICtrlCreateLabel("(" & $FreeDSpace & " of " & $TotalDSpace & "MB Free " & $PercentDFree, 75, 248, 350, 20)
            EndIf
    EndIf
    If $EState = "Good" Then
        $radioE = GUICtrlCreateRadio("Drive E", 10, 265, 120, 20)
        GUICtrlSetOnEvent($radioE, "RadioEClick")
        $FreeESpace = Round(DriveSpaceFree("E:\"), 0)
        $TotalESpace = Round(DriveSpaceTotal("E:\"), 0)
        $PercentEFree = $FreeESpace * 100 / $TotalESpace
        $PercentEFree = Round($PercentEFree, 1) & "%)"
        GUICtrlCreateLabel("(" & $FreeESpace & " of " & $TotalESpace & "MB Free " & $PercentEFree, 75, 268, 350, 20)
    EndIf
Else
    GUICtrlCreateLabel("You are using a Windows XP based operating system -- because of this we are unable to provide on-the-fly partition creation.", 10, 210, 350, 30)
    GUICtrlCreateLabel("We would suggest repartioning to specifications with a 3rd party utility or upgrade to a Windows 7/Vista based OS.",10,240,350,30)
EndIf
_GUICtrlTreeView_EndUpdate($hTreeView)
GUISetOnEvent($GUI_EVENT_CLOSE, "TreeEvents")
GUISetOnEvent($GUI_EVENT_PRIMARYDOWN, "TreeEvents")
GUISetState()
EndFunc
;;;;For All Drive D/E/Radio Buttons 1 is enabled and 0 is disabled
#Region<----->Functions for RadioButtons/CheckBoxTree
;Global $DriveDAvail = 0, $DriveDRamdisk = 0, $DriveDPartition = 0, $DriveEAvail = 0, $DriveEPartition = 0, $RadioC = 0, $RadioD = 0, $RadioE = 0
Func DriveDAllClick()
    $DriveDAvail = 1
    $DriveDRamdisk = 1
    $DriveDPartition = 0
EndFunc
Func DriveDAvailClick()
    $DriveDAvail = 1
EndFunc
Func DriveDRamdiskClick()
    $DriveDRamdisk = 1
EndFunc
Func DriveDPartitionclick()
    $DriveDPartition = 1
EndFunc
Func DriveEAllClick()
    $DriveEAvail = 1
    $DriveEPartition = 1
EndFunc
Func DriveEAvailClick()
    $DriveEAvail = 1
EndFunc
Func DriveEPartitionclick()
    $DriveEPartition = 1
EndFunc
Func RadioCClick()
    $RadioC = 1
EndFunc
Func RadioDClick()
    $RadioD = 1
EndFunc
Func RadioEClick()
    $RadioE = 1
EndFunc
Func NextButtonChooseFixClick()
    If $DriveDPartition = 1 Then
        If $RadioC = 1 Then
            FixChoices()
        ElseIf $RadioD = 1 Then
            FixChoices()
        ElseIf $RadioE = 1 Then
            FixChoices()
        Else
            MsgBox(0, "Error", "If you want to checkbox 'Make New Partition from Another Drive,' you must pick a drive below that to take space from.")
        EndIf
    ElseIf $DriveEPartition = 1 Then
        If $RadioC = 1 Then
            FixChoices()
        ElseIf $RadioD = 1 Then
            FixChoices()
        ElseIf $RadioE = 1 Then
            FixChoices()
        Else
            MsgBox(0, "Error", "If you want to checkbox 'Make New Partition from Another Drive,' you must pick a drive below that to take space from.")
        EndIf
    EndIf
    If $DriveDAvail = 1 Then
        FixChoices()
    ElseIf $DriveDRamdisk = 1 Then
        FixChoices()
    ElseIf $DriveDPartition = 1 Then
        FixChoices()
    ElseIf $DriveEAvail = 1 Then
        FixChoices()
    ElseIf $DriveEPartition = 1 Then
        FixChoices()
    Else
        $areyousure = MsgBox(4, "Are you sure?", "Are you sure you meant to not select any fixes and want to fix partitioning yourself?")
        If $areyousure = 6 Then
            Exit
        EndIf
    EndIf
EndFunc
#EndRegion<----->End Functions for RadioButtons/CheckBoxTree
#Region <----->CHECKBOX TREE FUNCTIONALITY<----->
Func TreeEvents()
    Switch @GUI_CtrlId
        Case $GUI_EVENT_CLOSE
            _GUICtrlTreeView_Destroy($hTreeView)
            GUIDelete()
            Exit
        Case $GUI_EVENT_PRIMARYDOWN
            Local $tMPos = _WinAPI_GetMousePos(True, $hTreeView)
            Local $tHitTest = _GUICtrlTreeView_HitTestEx($hTreeView, DllStructGetData($tMPos, 1), DllStructGetData($tMPos, 2))
            Local $iFlags = DllStructGetData($tHitTest, "Flags")
            Select
                Case BitAND($iFlags, $TVHT_ONITEMSTATEICON)
                    Local $hItem = _GUICtrlTreeView_HitTestItem($hTreeView, DllStructGetData($tMPos, 1), DllStructGetData($tMPos, 2))
                    Local $fChecked = False
                    If _GUICtrlTreeView_GetChecked($hTreeView, $hItem) Then $fChecked = True
                    _TvCheckbox($hItem, $fChecked)
            EndSelect
    EndSwitch
EndFunc   ;==>TreeEvents
Func _TvCheckbox($hTvItem, $fTvCheck)
    Local $hFirst, $hNext
    $hTvParent = _GUICtrlTreeView_GetParentHandle($hTreeView, $hTvItem)
    If $hTvParent = 0 Then $hTvParent = $hTvItem
    If $hTvParent Then _GUICtrlTreeView_SetChecked($hTreeView, $hTvParent, $fTvCheck)
    $hFirst = _GUICtrlTreeView_GetFirstChild($hTreeView, $hTvParent)
    If $hFirst Then
        $hNext = $hFirst
        While $hNext
            _GUICtrlTreeView_SetChecked($hTreeView, $hNext, $fTvCheck)
            If _GUICtrlTreeView_GetChildren($hTreeView, $hNext) Then _
                    _TvCheckbox(_GUICtrlTreeView_GetFirstChild($hTreeView, $hNext), $fTvCheck)
            $hNext = _GUICtrlTreeView_GetNextSibling($hTreeView, $hNext)
        WEnd
    EndIf
EndFunc   ;==>_TvCheckbox
#EndRegion<----->END CHECKBOX TREE FUNCTIONALITY<----->
#EndRegion <----->End Choose Fixes<----->

Thanks

Link to comment
Share on other sites

  • Moderators

cvocvo,

Me again - seems we have met a lot today! :P

I think this does what you want:

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

Global $fGeneralState = False, $fDisplayState = False, $fAllGeneralChecked = False, $fAllDisplayChecked = False
Global $aGeneralChildren[3], $aDisplayChildren[2]

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

GUISetState()

$hTreeView = _GUICtrlTreeView_Create($hGUI, 10, 10, 200, 150, BitOR($TVS_EDITLABELS, $TVS_HASBUTTONS, $TVS_HASLINES, $TVS_LINESATROOT, $TVS_DISABLEDRAGDROP, $TVS_SHOWSELALWAYS, $TVS_CHECKBOXES), $WS_EX_CLIENTEDGE)
_GUICtrlTreeView_BeginUpdate($hTreeView)
$hGeneralItem = _GUICtrlTreeView_Add($hTreeView, 0, "General")
$aGeneralChildren[0] = _GUICtrlTreeView_AddChild($hTreeView, $hGeneralItem, "About")
$aGeneralChildren[1] = _GUICtrlTreeView_AddChild($hTreeView, $hGeneralItem, "Computer")
$aGeneralChildren[2] = _GUICtrlTreeView_AddChild($hTreeView, $hGeneralItem, "User")

$hDisplayItem = _GUICtrlTreeView_Add($hTreeView, 0, "Display")
$aDisplayChildren[0] = _GUICtrlTreeView_AddChild($hTreeView, $hDisplayItem, "Rsolution")
$aDisplayChildren[1] = _GUICtrlTreeView_AddChild($hTreeView, $hDisplayItem, "Other")
_GUICtrlTreeView_EndUpdate($hTreeView)

While 1

    Switch GUIGetMsg()
        Case $GUI_EVENT_CLOSE
            Exit
    EndSwitch

    ; If General root checked, check all children and vice versa
    If _GUICtrlTreeView_GetChecked($hTreeView, $hGeneralItem) = True And $fGeneralState = False Then
        $fGeneralState = True
        For $i = 0 To UBound($aGeneralChildren) - 1
            _GUICtrlTreeView_SetChecked($hTreeView, $aGeneralChildren[$i], True)
            $fAllGeneralChecked = True
        Next
    ElseIf _GUICtrlTreeView_GetChecked($hTreeView, $hGeneralItem) = False And $fGeneralState = True Then
        $fGeneralState = False
        For $i = 0 To UBound($aGeneralChildren) - 1
            _GUICtrlTreeView_SetChecked($hTreeView, $aGeneralChildren[$i], False)
            $fAllGeneralChecked = False
        Next
    EndIf

    ; Count number of General children checked
    $iCount = 0
    For $i = 0 To UBound($aGeneralChildren) - 1
        If _GUICtrlTreeView_GetChecked($hTreeView, $aGeneralChildren[$i]) = True Then $iCount += 1
    Next
    ; If none checked - uncheck General root
    If $iCount = 0 And $fGeneralState = True Then
        _GUICtrlTreeView_SetChecked($hTreeView, $hGeneralItem, False)
        $fGeneralState = False
    ; If at least one checked - check General root if needed
    ElseIf $iCount > 0 And $fGeneralState = False Then
        _GUICtrlTreeView_SetChecked($hTreeView, $hGeneralItem, True)
        $fGeneralState = True
    EndIf
    ; If all children checked - set flag
    If $iCount = UBound($aGeneralChildren) Then
        $fAllGeneralChecked = True
    ; If flag was set and now not all are checked - uncheck General root and all children
    ElseIf $iCount = UBound($aGeneralChildren) - 1 Then
        If $fAllGeneralChecked = True Then
            $fGeneralState = False
            _GUICtrlTreeView_SetChecked($hTreeView, $hGeneralItem, False)
            $fAllGeneralChecked = True
            For $i = 0 To UBound($aGeneralChildren) - 1
                _GUICtrlTreeView_SetChecked($hTreeView, $aGeneralChildren[$i], False)
                $fAllGeneralChecked = False
            Next
        EndIf
    EndIf

    ; Do the same for the Display root/branch
    If _GUICtrlTreeView_GetChecked($hTreeView, $hDisplayItem) = True And $fDisplayState = False Then
        $fDisplayState = True
        For $i = 0 To UBound($aDisplayChildren) - 1
            _GUICtrlTreeView_SetChecked($hTreeView, $aDisplayChildren[$i], True)
            $fAllDisplayChecked = True
        Next
    ElseIf _GUICtrlTreeView_GetChecked($hTreeView, $hDisplayItem) = False And $fDisplayState = True Then
        $fDisplayState = False
        For $i = 0 To UBound($aDisplayChildren) - 1
            _GUICtrlTreeView_SetChecked($hTreeView, $aDisplayChildren[$i], False)
            $fAllDisplayChecked = False
        Next
    EndIf

    $iCount = 0
    For $i = 0 To UBound($aDisplayChildren) - 1
        If _GUICtrlTreeView_GetChecked($hTreeView, $aDisplayChildren[$i]) = True Then $iCount += 1
    Next
    If $iCount = 0 And $fDisplayState = True Then
        _GUICtrlTreeView_SetChecked($hTreeView, $hDisplayItem, False)
        $fDisplayState = False
    ElseIf $iCount > 0 And $fDisplayState = False Then
        _GUICtrlTreeView_SetChecked($hTreeView, $hDisplayItem, True)
        $fDisplayState = True
    EndIf
    If $iCount = UBound($aDisplayChildren) Then
        $fAllDisplayChecked = True
    ElseIf $iCount = UBound($aDisplayChildren) - 1 Then
        If $fAllDisplayChecked = True Then
            $fDisplayState = False
            _GUICtrlTreeView_SetChecked($hTreeView, $hDisplayItem, False)
            $fAllDisplayChecked = True
            For $i = 0 To UBound($aDisplayChildren) - 1
                _GUICtrlTreeView_SetChecked($hTreeView, $aDisplayChildren[$i], False)
                $fAllDisplayChecked = False
            Next
        EndIf
    EndIf

WEnd

There must be an easier way - I will look again tomorrow after a night's sleep and a round of golf to clear the brain. :mellow:

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

You are an autoit ninja -- that works well enough for what I'll be using it for. Now I just need to implement it.

Thanks

Edit: So, I've implemented it, but we have a problem. Because I'm putting all of this within a function, that While loop makes everything get stuck. Consequently, the rest of the window doesn't load and the button on my GUI window doesn't work because everything is stuck in a loop. For this reason I had everything working in a couple functions, but they aren't working like I want them to.

The other thing I want is to make sure the checkbox tree opens expanded.

Edited by cvocvo
Link to comment
Share on other sites

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

Local $hGUI, $hTree, $hItem, $hSubItem, $hSubZero

$hGUI = GUICreate("Test", 220, 300)
$hTree = _GUICtrlTreeView_Create($hGUI, 20, 20, 200, 260, BitOR($GUI_SS_DEFAULT_TREEVIEW, $TVS_CHECKBOXES))
GUISetState()

_GUICtrlTreeView_BeginUpdate($hTree)
    For $x = 1 To 10
        $hItem = _GUICtrlTreeView_Add($hTree, 0, StringFormat("[%02d] New Item", $x))
        _GUICtrlTreeView_SetChecked($hTree, $hItem)
        For $y = 1 To 5
            $hSubItem = _GUICtrlTreeView_AddChild($hTree, $hItem, StringFormat("[%02d] New Child", $y), 0)
            _GUICtrlTreeView_SetChecked($hTree, $hSubItem)
            For $z = 1 To 3
                $hSubZero = _GUICtrlTreeView_AddChild($hTree, $hSubItem, StringFormat("[%02d] New Grandchild", $z), 0)
                _GUICtrlTreeView_SetChecked($hTree, $hSubZero)
                _GUICtrlTreeView_Expand($hTree, $hSubZero)
            Next
        Next
    Next
_GUICtrlTreeView_EndUpdate($hTree)

GUIRegisterMsg($WM_NOTIFY, "_WM_NOTIFY")

Do
Until GUIGetMsg() = $GUI_EVENT_CLOSE

GUIDelete()

Func _WM_NOTIFY($hWnd, $iMsg, $iwParam, $ilParam)
    Local $hWndFrom, $iIDFrom, $iCode, $tNMHDR
    Local $iPos, $iX, $iY, $tPt, $iHitTest, $fWasChecked
    Local $hItem

    $tNMHDR = DllStructCreate($tagNMHDR, $ilParam)
    $hWndFrom = HWnd(DllStructGetData($tNMHDR, "hWndFrom"))
    $iIDFrom = DllStructGetData($tNMHDR, "IDFrom")
    $iCode = DllStructGetData($tNMHDR, "Code")

    Switch $hWndFrom
        Case $hTree
            Switch $iCode
                Case $NM_CLICK
                    $iPos = _WinAPI_GetMessagePos()
                    $iX = BitAND($iPos, 0xFFFF)
                    $iY = BitShift($iPos, 16)
                    $tPt = DllStructCreate($tagPOINT)
                    DllStructSetData($tPt, "X", $iX)
                    DllStructSetData($tPt, "Y", $iY)
                    _WinAPI_ScreenToClient($hTree, $tPt)
                    $iX = DllStructGetData($tPt, "X")
                    $iY = DllStructGetData($tPt, "Y")

                    $tTVHTInfo = _GUICtrlTreeView_HitTestEx($hTree, $iX, $iY)
                    If DllStructGetData($tTVHTInfo, "Flags") = $TVHT_ONITEMSTATEICON Then
                        $hItem = DllStructGetData($tTVHTInfo, "Item")
                        $fWasChecked = _GUICtrlTreeView_GetChecked($hTree, $hItem)

                        If $fWasChecked Then
                            _GUICtrlTreeView_BeginUpdate($hTree)
                            _Uncheck($hItem)
                            _GUICtrlTreeView_EndUpdate($hTree)
                        Else
                            _GUICtrlTreeView_BeginUpdate($hTree)
                            _Check($hItem)
                            _GUICtrlTreeView_EndUpdate($hTree)
                        EndIf

                    EndIf
            EndSwitch
    EndSwitch
    Return $GUI_RUNDEFMSG
EndFunc

Func _Uncheck($hItem)
    Local $hParent, $hItemCur, $iLevel

    $iLevel = _GUICtrlTreeView_Level($hTree, $hItem)
    $hItemCur = _GUICtrlTreeView_GetFirstChild($hTree, $hItem)
    While $hItemCur And _GUICtrlTreeView_Level($hTree, $hItemCur) > $iLevel
        _GUICtrlTreeView_SetChecked($hTree, $hItemCur, False)
        $hItemCur = _GUICtrlTreeView_GetNext($hTree, $hItemCur)
    WEnd

    $hParent = _GUICtrlTreeView_GetParentHandle($hTree, $hItem)
    If $hParent Then
        While $hParent
            If $hParent <> $hItem Then _GUICtrlTreeView_SetChecked($hTree, $hParent, False)
            $hParent = _GUICtrlTreeView_GetParentHandle($hTree, $hParent)
        WEnd
    EndIf
EndFunc

Func _Check($hItem)
    Local $hParent, $hItemCur, $iLevel

    $iLevel = _GUICtrlTreeView_Level($hTree, $hItem)
    $hItemCur = _GUICtrlTreeView_GetFirstChild($hTree, $hItem)
    While $hItemCur And _GUICtrlTreeView_Level($hTree, $hItemCur) > $iLevel
        _GUICtrlTreeView_SetChecked($hTree, $hItemCur)
        $hItemCur = _GUICtrlTreeView_GetNext($hTree, $hItemCur)
    WEnd

    $hParent = _GUICtrlTreeView_GetParentHandle($hTree, $hItem)
    While $hParent
        $hItemCur = _GUICtrlTreeView_GetFirstChild($hTree, $hParent)
        While $hItemCur
            If Not _GUICtrlTreeView_GetChecked($hTree, $hItemCur) And $hItemCur <> $hItem Then ExitLoop 2
            $hItemCur = _GUICtrlTreeView_GetNextSibling($hTree, $hItemCur)
        WEnd

        _GUICtrlTreeView_SetChecked($hTree, $hParent)
        $hParent = _GUICtrlTreeView_GetParentHandle($hTree, $hParent)
    WEnd
EndFunc

Func _WinAPI_GetMessagePos()
    Local $aResult = DllCall("user32.dll", "uint", "GetMessagePos")

    If @error Then Return SetError(@error, @extended, 0)
    Return $aResult[0]
EndFunc

Link to comment
Share on other sites

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

Local $hGUI, $hTree, $hItem, $hSubItem, $hSubZero

$hGUI = GUICreate("Test", 220, 300)
$hTree = _GUICtrlTreeView_Create($hGUI, 20, 20, 200, 260, BitOR($GUI_SS_DEFAULT_TREEVIEW, $TVS_CHECKBOXES))
GUISetState()

_GUICtrlTreeView_BeginUpdate($hTree)
    For $x = 1 To 10
        $hItem = _GUICtrlTreeView_Add($hTree, 0, StringFormat("[%02d] New Item", $x))
        _GUICtrlTreeView_SetChecked($hTree, $hItem)
        For $y = 1 To 5
            $hSubItem = _GUICtrlTreeView_AddChild($hTree, $hItem, StringFormat("[%02d] New Child", $y), 0)
            _GUICtrlTreeView_SetChecked($hTree, $hSubItem)
            For $z = 1 To 3
                $hSubZero = _GUICtrlTreeView_AddChild($hTree, $hSubItem, StringFormat("[%02d] New Grandchild", $z), 0)
                _GUICtrlTreeView_SetChecked($hTree, $hSubZero)
                _GUICtrlTreeView_Expand($hTree, $hSubZero)
            Next
        Next
    Next
_GUICtrlTreeView_EndUpdate($hTree)

GUIRegisterMsg($WM_NOTIFY, "_WM_NOTIFY")

Do
Until GUIGetMsg() = $GUI_EVENT_CLOSE

GUIDelete()

Func _WM_NOTIFY($hWnd, $iMsg, $iwParam, $ilParam)
    Local $hWndFrom, $iIDFrom, $iCode, $tNMHDR
    Local $iPos, $iX, $iY, $tPt, $iHitTest, $fWasChecked
    Local $hItem

    $tNMHDR = DllStructCreate($tagNMHDR, $ilParam)
    $hWndFrom = HWnd(DllStructGetData($tNMHDR, "hWndFrom"))
    $iIDFrom = DllStructGetData($tNMHDR, "IDFrom")
    $iCode = DllStructGetData($tNMHDR, "Code")

    Switch $hWndFrom
        Case $hTree
            Switch $iCode
                Case $NM_CLICK
                    $iPos = _WinAPI_GetMessagePos()
                    $iX = BitAND($iPos, 0xFFFF)
                    $iY = BitShift($iPos, 16)
                    $tPt = DllStructCreate($tagPOINT)
                    DllStructSetData($tPt, "X", $iX)
                    DllStructSetData($tPt, "Y", $iY)
                    _WinAPI_ScreenToClient($hTree, $tPt)
                    $iX = DllStructGetData($tPt, "X")
                    $iY = DllStructGetData($tPt, "Y")

                    $tTVHTInfo = _GUICtrlTreeView_HitTestEx($hTree, $iX, $iY)
                    If DllStructGetData($tTVHTInfo, "Flags") = $TVHT_ONITEMSTATEICON Then
                        $hItem = DllStructGetData($tTVHTInfo, "Item")
                        $fWasChecked = _GUICtrlTreeView_GetChecked($hTree, $hItem)

                        If $fWasChecked Then
                            _GUICtrlTreeView_BeginUpdate($hTree)
                            _Uncheck($hItem)
                            _GUICtrlTreeView_EndUpdate($hTree)
                        Else
                            _GUICtrlTreeView_BeginUpdate($hTree)
                            _Check($hItem)
                            _GUICtrlTreeView_EndUpdate($hTree)
                        EndIf

                    EndIf
            EndSwitch
    EndSwitch
    Return $GUI_RUNDEFMSG
EndFunc

Func _Uncheck($hItem)
    Local $hParent, $hItemCur, $iLevel

    $iLevel = _GUICtrlTreeView_Level($hTree, $hItem)
    $hItemCur = _GUICtrlTreeView_GetFirstChild($hTree, $hItem)
    While $hItemCur And _GUICtrlTreeView_Level($hTree, $hItemCur) > $iLevel
        _GUICtrlTreeView_SetChecked($hTree, $hItemCur, False)
        $hItemCur = _GUICtrlTreeView_GetNext($hTree, $hItemCur)
    WEnd

    $hParent = _GUICtrlTreeView_GetParentHandle($hTree, $hItem)
    If $hParent Then
        While $hParent
            If $hParent <> $hItem Then _GUICtrlTreeView_SetChecked($hTree, $hParent, False)
            $hParent = _GUICtrlTreeView_GetParentHandle($hTree, $hParent)
        WEnd
    EndIf
EndFunc

Func _Check($hItem)
    Local $hParent, $hItemCur, $iLevel

    $iLevel = _GUICtrlTreeView_Level($hTree, $hItem)
    $hItemCur = _GUICtrlTreeView_GetFirstChild($hTree, $hItem)
    While $hItemCur And _GUICtrlTreeView_Level($hTree, $hItemCur) > $iLevel
        _GUICtrlTreeView_SetChecked($hTree, $hItemCur)
        $hItemCur = _GUICtrlTreeView_GetNext($hTree, $hItemCur)
    WEnd

    $hParent = _GUICtrlTreeView_GetParentHandle($hTree, $hItem)
    While $hParent
        $hItemCur = _GUICtrlTreeView_GetFirstChild($hTree, $hParent)
        While $hItemCur
            If Not _GUICtrlTreeView_GetChecked($hTree, $hItemCur) And $hItemCur <> $hItem Then ExitLoop 2
            $hItemCur = _GUICtrlTreeView_GetNextSibling($hTree, $hItemCur)
        WEnd

        _GUICtrlTreeView_SetChecked($hTree, $hParent)
        $hParent = _GUICtrlTreeView_GetParentHandle($hTree, $hParent)
    WEnd
EndFunc

Func _WinAPI_GetMessagePos()
    Local $aResult = DllCall("user32.dll", "uint", "GetMessagePos")

    If @error Then Return SetError(@error, @extended, 0)
    Return $aResult[0]
EndFunc

I'm afraid yours suffers similar downfalls as other implementations.

The loop breaks my Next button because I am putting all of this inside a function. I am also unsure how I would implement differently named parents with different variables (like I did in my original post) so that I can map each checkbox to a variable. --> You just have a loop that creates each new item, where as I need to conditionally populate two different parents each with a different variable and then conditionally populate different children with different variables.

What yours does do though is have a reliable, working implementation of a properly functioning checkbox tree.

Edit:

Upon further tweaking, I am able to get your implementation to work with the Next button by commenting out:

;Do
;Until GUIGetMsg() = $GUI_EVENT_CLOSE
;GUIDelete()

(Not really sure if that's necessary)

That just leaves the question how would I be able conditionally populate two different parents each with a different variable and then conditionally populate different children with different variables?

Edited by cvocvo
Link to comment
Share on other sites

Examples should be demonstrative. I've never seen a real world code example in MSDN site that does anything else other then explaining how to achieve or implement the subject in hand. You can build the tree using loops with arrays, or fill in the tree items one by one; whatever suites your case.

Link to comment
Share on other sites

Let me restructure my question/concern a little bit with a simple example.

Currently we have something that looks like this:

$hItem = _GUICtrlTreeView_Add($hTree, 0, StringFormat("[%02d] New Item", $x))
        _GUICtrlTreeView_SetChecked($hTree, $hItem)
        For $y = 1 To 5
            $hSubItem = _GUICtrlTreeView_AddChild($hTree, $hItem, StringFormat("[%02d] New Child", $y), 0)
            _GUICtrlTreeView_SetChecked($hTree, $hSubItem)
            For $z = 1 To 3
                $hSubZero = _GUICtrlTreeView_AddChild($hTree, $hSubItem, StringFormat("[%02d] New Grandchild", $z), 0)
                _GUICtrlTreeView_SetChecked($hTree, $hSubZero)
                _GUICtrlTreeView_Expand($hTree, $hSubZero)

As you can see $hItem, $hSubItem, and $hSubZero are the variables being set for each of the checkbox tree items. I can't go in and change $hItem to $hItem1 and $hItem2 because the functions aren't looking for those, they're only interested in $hItem.

So if I can't change those, how would I go about getting a value from each checked checkbox. Or stated differently, I want to set a variable equal to each box that gets checked, as it gets checked or unchecked.

Link to comment
Share on other sites

#include <GUIConstantsEx.au3>
#include <GUITreeView.au3>
#include <WindowsConstants.au3>
#include <Constants.au3>
Opt("GUIOnEventMode", 1)

Local $hGUI, $Tree, $hTree, $hItems[40][2] = [[0]] ; [hItem, Function]
Local $DriveDAvail, $DriveDRamdisk, $DriveDPartition, $DriveEAvail, $DriveEPartition
Local $Bad, $OSVersion, $CState, $DState, $EState
Local $idParent1, $idLevel2P1, $idLevel3P1, $idLevel4P1, $idParent2, $idLevel2P2, $idLevel3P2

$hGUI = GUICreate("Test", 400, 400)
GUISetOnEvent($GUI_EVENT_CLOSE, "_Quit")
$Tree = GUICtrlCreateTreeView(20, 20, 360, 360, BitOR($GUI_SS_DEFAULT_TREEVIEW, $TVS_CHECKBOXES))
$hTree = GUICtrlGetHandle($Tree)

$Bad = 0
$OSVersion = "XP"
$CState = "Good"
$DState = "Bad"
$EState = "Bad"

_GUICtrlTreeView_BeginUpdate($hTree)

    If $DState = "Bad" Then
        $idParent1 = GUICtrlCreateTreeViewItem('Drive D', $Tree)
        $hItems[0][0] += 1
        $hItems[$hItems[0][0]][0] = GUICtrlGetHandle($idParent1)
        $hItems[$hItems[0][0]][1] = "DriveDAllClick"

        $idLevel2P1 = GUICtrlCreateTreeViewItem('Make Drive Letter D:\ Available for Use', $idParent1)
        $hItems[0][0] += 1
        $hItems[$hItems[0][0]][0] = GUICtrlGetHandle($idLevel2P1)
        $hItems[$hItems[0][0]][1] = "DriveDAvailClick"

        $idLevel3P1 = GUICtrlCreateTreeViewItem('Install RamDisk on Drive D', $idParent1)
        $hItems[0][0] += 1
        $hItems[$hItems[0][0]][0] = GUICtrlGetHandle($idLevel3P1)
        $hItems[$hItems[0][0]][1] = "DriveDRamdiskClick"

        If $OSVersion = "7" Then
            $idLevel4P1 = GUICtrlCreateTreeViewItem('Make New Partition from Another Drive [*If RamDisk is checked it will nullify this checkbox*]', $idParent1)
            $hItems[0][0] += 1
            $hItems[$hItems[0][0]][0] = GUICtrlGetHandle($idLevel4P1)
            $hItems[$hItems[0][0]][1] = "DriveDPartitionclick"
        EndIf
        _GUICtrlTreeView_Expand($hTree, GUICtrlGetHandle($idParent1))
    EndIf

    If $EState = "Bad" Then
        $idParent2 = GUICtrlCreateTreeViewItem('Drive E', $Tree)
        $hItems[0][0] += 1
        $hItems[$hItems[0][0]][0] = GUICtrlGetHandle($idParent2)
        $hItems[$hItems[0][0]][1] = "DriveEAllClick"

        $idLevel2P2 = GUICtrlCreateTreeViewItem('Make Drive Letter E:\ Available for Use', $idParent2)
        $hItems[0][0] += 1
        $hItems[$hItems[0][0]][0] = GUICtrlGetHandle($idLevel2P2)
        $hItems[$hItems[0][0]][1] = "DriveEAvailClick"

        If $OSVersion = "7" Then
            $idLevel3P2 = GUICtrlCreateTreeViewItem('Make New Partition from Another Drive' & @CRLF & '[*If RamDisk is checked it will nullify this checkbox*]', $idParent2)
            $hItems[0][0] += 1
            $hItems[$hItems[0][0]][0] = GUICtrlGetHandle($idLevel3P2)
            $hItems[$hItems[0][0]][1] = "DriveEPartitionclick"
        EndIf
        _GUICtrlTreeView_Expand($hTree, GUICtrlGetHandle($idParent2))
    EndIf

_GUICtrlTreeView_EndUpdate($hTree)

ReDim $hItems[$hItems[0][0]+1][2]

GUIRegisterMsg($WM_NOTIFY, "_WM_NOTIFY")
GUISetState()

While 1
    Sleep(20)
WEnd

Func _Quit()
    ConsoleWrite(StringFormat("%d %d %d %d %d\n",  $DriveDAvail, $DriveDRamdisk, $DriveDPartition, $DriveEAvail, $DriveEPartition))
    Exit
EndFunc

Func DriveDAllClick()
    $DriveDAvail = 1
    $DriveDRamdisk = 1
    $DriveDPartition = 0
EndFunc

Func DriveDAvailClick()
    $DriveDAvail = 1
EndFunc

Func DriveDRamdiskClick()
    $DriveDRamdisk = 1
EndFunc

Func DriveDPartitionclick()
    $DriveDPartition = 1
EndFunc

Func DriveEAllClick()
    $DriveEAvail = 1
    $DriveEPartition = 1
EndFunc

Func DriveEAvailClick()
    $DriveEAvail = 1
EndFunc

Func DriveEPartitionclick()
    $DriveEPartition = 1
EndFunc

Func _WM_NOTIFY($hWnd, $iMsg, $iwParam, $ilParam)
    Local $hWndFrom, $iIDFrom, $iCode, $tNMHDR
    Local $iPos, $iX, $iY, $tPt, $iHitTest, $fWasChecked
    Local $hItem

    $tNMHDR = DllStructCreate($tagNMHDR, $ilParam)
    $hWndFrom = HWnd(DllStructGetData($tNMHDR, "hWndFrom"))
    $iIDFrom = DllStructGetData($tNMHDR, "IDFrom")
    $iCode = DllStructGetData($tNMHDR, "Code")

    Switch $hWndFrom
        Case $hTree
            Switch $iCode
                Case $NM_CLICK
                    $iPos = _WinAPI_GetMessagePos()
                    $iX = BitAND($iPos, 0xFFFF)
                    $iY = BitShift($iPos, 16)
                    $tPt = DllStructCreate($tagPOINT)
                    DllStructSetData($tPt, "X", $iX)
                    DllStructSetData($tPt, "Y", $iY)
                    _WinAPI_ScreenToClient($hTree, $tPt)
                    $iX = DllStructGetData($tPt, "X")
                    $iY = DllStructGetData($tPt, "Y")

                    $tTVHTInfo = _GUICtrlTreeView_HitTestEx($hTree, $iX, $iY)
                    If DllStructGetData($tTVHTInfo, "Flags") = $TVHT_ONITEMSTATEICON Then
                        $hItem = DllStructGetData($tTVHTInfo, "Item")
                        $fWasChecked = _GUICtrlTreeView_GetChecked($hTree, $hItem)

                        If $fWasChecked Then
                            _GUICtrlTreeView_BeginUpdate($hTree)
                            _Uncheck($hItem)
                            _GUICtrlTreeView_EndUpdate($hTree)
                        Else
                            _GUICtrlTreeView_BeginUpdate($hTree)
                            _CallItemFunc($hItem)
                            _Check($hItem)
                            _GUICtrlTreeView_EndUpdate($hTree)
                        EndIf

                    EndIf
            EndSwitch
    EndSwitch
    Return $GUI_RUNDEFMSG
EndFunc

Func _Uncheck($hItem)
    Local $hParent, $hItemCur, $iLevel

    $iLevel = _GUICtrlTreeView_Level($hTree, $hItem)
    $hItemCur = _GUICtrlTreeView_GetFirstChild($hTree, $hItem)
    While $hItemCur And _GUICtrlTreeView_Level($hTree, $hItemCur) > $iLevel
        _GUICtrlTreeView_SetChecked($hTree, $hItemCur, False)
        $hItemCur = _GUICtrlTreeView_GetNext($hTree, $hItemCur)
    WEnd

    $hParent = _GUICtrlTreeView_GetParentHandle($hTree, $hItem)
    If $hParent Then
        While $hParent
            If $hParent <> $hItem Then _GUICtrlTreeView_SetChecked($hTree, $hParent, False)
            $hParent = _GUICtrlTreeView_GetParentHandle($hTree, $hParent)
        WEnd
    EndIf
EndFunc

Func _Check($hItem)
    Local $hParent, $hItemCur, $iLevel

    $iLevel = _GUICtrlTreeView_Level($hTree, $hItem)
    $hItemCur = _GUICtrlTreeView_GetFirstChild($hTree, $hItem)
    While $hItemCur And _GUICtrlTreeView_Level($hTree, $hItemCur) > $iLevel
        _GUICtrlTreeView_SetChecked($hTree, $hItemCur)
        _CallItemFunc($hItemCur)
        $hItemCur = _GUICtrlTreeView_GetNext($hTree, $hItemCur)
    WEnd

    $hParent = _GUICtrlTreeView_GetParentHandle($hTree, $hItem)
    While $hParent
        $hItemCur = _GUICtrlTreeView_GetFirstChild($hTree, $hParent)
        While $hItemCur
            If Not _GUICtrlTreeView_GetChecked($hTree, $hItemCur) And $hItemCur <> $hItem Then ExitLoop 2
            $hItemCur = _GUICtrlTreeView_GetNextSibling($hTree, $hItemCur)
        WEnd

        _GUICtrlTreeView_SetChecked($hTree, $hParent)
        _CallItemFunc($hParent)
        $hParent = _GUICtrlTreeView_GetParentHandle($hTree, $hParent)
    WEnd
EndFunc

Func _WinAPI_GetMessagePos()
    Local $aResult = DllCall("user32.dll", "uint", "GetMessagePos")

    If @error Then Return SetError(@error, @extended, 0)
    Return $aResult[0]
EndFunc

Func _CallItemFunc($hItem)
    For $i = 1 To $hItems[0][0]
        If $hItem = $hItems[$i][0] Then
            Call($hItems[$i][1])
            ExitLoop
        EndIf
    Next
EndFunc

You need to implement the uncheck function calls. As it's now, once $DriveDPartition, etc.. is set, nothing updates the variable back to uncheck.

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

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...