Jump to content

Treeview Child, automatically checking its Parents


ndw
 Share

Recommended Posts

Good afternoon, I am new to AutoIt and the forums so, hello :graduated:

I have been looking through your website and the wiki site for a few days now to try and solve an problem i'm facing. I am using a TreeView control with check boxes and would like to make it so when a user clicks on a child, its parent, and parent's parent etc are also ticked if not already.

I have discovered similar postings on here but with my bad knowledge of the area, i couldn't understand the solutions given (notably post, though this is primarily focused on a select all type action, it performs the same action i want to achieve).

My confusion is with the arrays. I create the items in my TreeView manually (included below) and so don't understand how to apply the same "checks" for the items state when i can't step through the items in an array.

$winGUI = GUICreate("Food_Drink", $width, $height, $x, $y)
$tvItems = GUICtrlCreateTreeView(8, 16, 241, 305, BitOR($GUI_SS_DEFAULT_TREEVIEW, $TVS_CHECKBOXES), _
    $WS_EX_DLGMODALFRAME+$WS_EX_CLIENTEDGE)
$Food = GUICtrlCreateTreeViewItem("Food", $tvItems)
$Fruit = GUICtrlCreateTreeViewItem("Fruit", $Food)
$Apple = GUICtrlCreateTreeViewItem("Apple", $Fruit)
$Meat = GUICtrlCreateTreeViewItem("Meat", $Food)
$Steak = GUICtrlCreateTreeViewItem("Steak", $Meat)
$Chicken = GUICtrlCreateTreeViewItem("Chicken", $Meat)
$Dairy = GUICtrlCreateTreeViewItem("Dairy", $Food)
$Cheese = GUICtrlCreateTreeViewItem("Cheese", $Dairy)
$Drink = GUICtrlCreateTreeViewItem("Drinks", $tvItems)
$Water = GUICtrlCreateTreeViewItem("Water", $Drink)
$Fizzy = GUICtrlCreateTreeViewItem("Fizzy", $Drink)
$Cola = GUICtrlCreateTreeViewItem("Cola", $Fizzy)
$Juice = GUICtrlCreateTreeViewItem("Juice", $Drink)
$OrangeJuice = GUICtrlCreateTreeViewItem("OrangeJuice", $Juice)
$HotDrink = GUICtrlCreateTreeViewItem("Hot Drinks", $Drink)
$Tea = GUICtrlCreateTreeViewItem("Tea", $HotDrink)
$Coffee = GUICtrlCreateTreeViewItem("Coffee", $HotDrink)

Ultimately, clicking on the "Coffee" checkbox should also check "Hot Drink" and "Drink".

Thank you for your time in reading this and i'm sorry it's probably confusing as hell. I've been hitting my head against a wall for a while!

Regards, NDW (novice scripter)

Link to comment
Share on other sites

  • Moderators

ndw,

Welcome to the AutoIt forum. :graduated:

No need for arrays (although you should learn about them in due course :)) - just keep running back up the tree to look for parents to check:

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

$winGUI = GUICreate("Food_Drink", 500, 500)

$tvItems = GUICtrlCreateTreeView(8, 16, 241, 305, BitOR($GUI_SS_DEFAULT_TREEVIEW, $TVS_CHECKBOXES), _
    $WS_EX_DLGMODALFRAME+$WS_EX_CLIENTEDGE)
    $hTV = GUICtrlGetHandle(-1) ; Get handle of the control - works better in the UDF commands used later on
$Food = GUICtrlCreateTreeViewItem("Food", $tvItems)
$Fruit = GUICtrlCreateTreeViewItem("Fruit", $Food)
$Apple = GUICtrlCreateTreeViewItem("Apple", $Fruit)
$Meat = GUICtrlCreateTreeViewItem("Meat", $Food)
$Steak = GUICtrlCreateTreeViewItem("Steak", $Meat)
$Chicken = GUICtrlCreateTreeViewItem("Chicken", $Meat)
$Dairy = GUICtrlCreateTreeViewItem("Dairy", $Food)
$Cheese = GUICtrlCreateTreeViewItem("Cheese", $Dairy)
$Drink = GUICtrlCreateTreeViewItem("Drinks", $tvItems)
$Water = GUICtrlCreateTreeViewItem("Water", $Drink)
$Fizzy = GUICtrlCreateTreeViewItem("Fizzy", $Drink)
$Cola = GUICtrlCreateTreeViewItem("Cola", $Fizzy)
$Juice = GUICtrlCreateTreeViewItem("Juice", $Drink)
$OrangeJuice = GUICtrlCreateTreeViewItem("OrangeJuice", $Juice)
$HotDrink = GUICtrlCreateTreeViewItem("Hot Drinks", $Drink)
$Tea = GUICtrlCreateTreeViewItem("Tea", $HotDrink)
$Coffee = GUICtrlCreateTreeViewItem("Coffee", $HotDrink)

GUISetState()

While 1

    Switch GUIGetMsg()
        Case $GUI_EVENT_CLOSE
            Exit
    EndSwitch

    ; Get selected item
    $hSelected = _GUICtrlTreeView_GetSelection($hTV)
    ; Is it checked?
    If _GUICtrlTreeView_GetChecked($hTV, $hSelected) Then
        ; If so check its parent
        _Check_Parents($hSelected)
    EndIf

WEnd

Func _Check_Parents($hHandle)

    ; Get the handle of the parent
    $hParent = _GUICtrlTreeView_GetParentHandle($hTV, $hHandle)
    ; If there is no parent
    If $hParent = 0 Then
        Return
    EndIf
    ; Check the parent
    _GUICtrlTreeView_SetChecked($hTV, $hParent)
    ; And look for the grandparent and so on
    _Check_Parents($hParent)

EndFunc

All clear? Please ask if not. ;)

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

Hello Melba, this works perfectly and thank you for taking the time to help. I have another question to trouble you though, so i understand it all!

You use a handle for the treeView using "$hTV = GUICtrlGetHandle(-1)", what is the -1 for?

Link to comment
Share on other sites

  • Moderators

ndw,

When used in this contect, -1 is shorthand for "the last control created". :graduated:

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

Ah ha, so if you were to have made the handle someplace else, you would have put "$hTV = GUICtrlGetHandle($tvItems)" in its place? I'm sorry for the terribly newbie questions, but i understand it now and want to say thank you again :graduated: Now to work on a Select All function but have an idea how to go about it!

Link to comment
Share on other sites

One final question, i'm making a reverse of the function where if you uncheck the parent, it's children all untick, but looking at the GUITree UDFs, there doesn't seem to be "a _GUICtrlTreeView_GetChildHandle" like the "_GUICtrlTreeView_GetParentHandle". Is this just me being silly or will i have to this another way?

Link to comment
Share on other sites

  • Moderators

ndw,

so if you were to have made the handle someplace else, you would have put "$hTV = GUICtrlGetHandle($tvItems)" in its place?

Exactly! :graduated:

Now to work on a Select All function

I hope you are looking at arrays - here is a good tutorial to get you started. ;)

M23

Edit: Tags again. :)

Edited by Melba23

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

Thank you again and i've swapped everything over to an array now and the Select All is working great :graduated:

I did a double post most likely when you were replying to one of my many questions. It's regarding being able to get the handle of a child. What i'm wanting to do is, using my first example, if i uncheck "Drink", it will go through and uncheck everything underneath it. I was going to do this using a similar function to the one you provided, but use it to step through the children and uncheck. I found there isn't a "_GUICtrlTreeView_GetChildHandle" and i ran in to some problems when looking for the "uncheck" action in the GUIGetMsg loop that cause it to loop itself in to an error.

Again, sorry for my novice-ness!

Link to comment
Share on other sites

  • Moderators

ndw,

I found there isn't a "_GUICtrlTreeView_GetChildHandle"

Someone did not look very hard! ;)

_GUICtrlTreeView_GetFirstChild - Retrieves the first child item of the specified item

Success: The handle of the first child item

But it is a bit more complex to uncheck than to check as you can see:

#include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>
#Include <GuiTreeView.au3>
#include <Array.au3>

; Create an array to hold the handles and checkstate of the treeview items
Global $aItems[17][2]

$winGUI = GUICreate("Food_Drink", 500, 500)

$tvItems = GUICtrlCreateTreeView(8, 16, 241, 305, BitOR($GUI_SS_DEFAULT_TREEVIEW, $TVS_CHECKBOXES), _
    $WS_EX_DLGMODALFRAME+$WS_EX_CLIENTEDGE)
    $hTV = GUICtrlGetHandle(-1) ; Get handle of the control - works better in the UDF commands used later on
$Food = GUICtrlCreateTreeViewItem("Food", $tvItems)
$aItems[0][0] = GuiCtrlGetHandle($Food) ; Set the [n][0] element to the handle of the item
$Fruit = GUICtrlCreateTreeViewItem("Fruit", $Food)
$aItems[1][0] = GuiCtrlGetHandle($Fruit)
$Apple = GUICtrlCreateTreeViewItem("Apple", $Fruit)
$aItems[2][0] = GuiCtrlGetHandle($Apple)
$Meat = GUICtrlCreateTreeViewItem("Meat", $Food)
$aItems[3][0] = GuiCtrlGetHandle($Meat)
$Steak = GUICtrlCreateTreeViewItem("Steak", $Meat)
$aItems[4][0] = GuiCtrlGetHandle($Steak)
$Chicken = GUICtrlCreateTreeViewItem("Chicken", $Meat)
$aItems[5][0] = GuiCtrlGetHandle($Chicken)
$Dairy = GUICtrlCreateTreeViewItem("Dairy", $Food)
$aItems[6][0] = GuiCtrlGetHandle($Dairy)
$Cheese = GUICtrlCreateTreeViewItem("Cheese", $Dairy)
$aItems[7][0] = GuiCtrlGetHandle($Cheese)
$Drink = GUICtrlCreateTreeViewItem("Drinks", $tvItems)
$aItems[8][0] = GuiCtrlGetHandle($Drink)
$Water = GUICtrlCreateTreeViewItem("Water", $Drink)
$aItems[9][0] = GuiCtrlGetHandle($Water)
$Fizzy = GUICtrlCreateTreeViewItem("Fizzy", $Drink)
$aItems[10][0] = GuiCtrlGetHandle($Fizzy)
$Cola = GUICtrlCreateTreeViewItem("Cola", $Fizzy)
$aItems[11][0] = GuiCtrlGetHandle($Cola)
$Juice = GUICtrlCreateTreeViewItem("Juice", $Drink)
$aItems[12][0] = GuiCtrlGetHandle($Juice)
$OrangeJuice = GUICtrlCreateTreeViewItem("OrangeJuice", $Juice)
$aItems[13][0] = GuiCtrlGetHandle($OrangeJuice)
$HotDrink = GUICtrlCreateTreeViewItem("Hot Drinks", $Drink)
$aItems[14][0] = GuiCtrlGetHandle($HotDrink)
$Tea = GUICtrlCreateTreeViewItem("Tea", $HotDrink)
$aItems[15][0] = GuiCtrlGetHandle($Tea)
$Coffee = GUICtrlCreateTreeViewItem("Coffee", $HotDrink)
$aItems[16][0] = GuiCtrlGetHandle($Coffee)

; Create buttons to set/clear all
$hSet = GUICtrlCreateButton("Set All", 300, 10, 80, 30)
$hClear = GUICtrlCreateButton("Clear All", 300, 50, 80, 30)

GUISetState()

; This will store the last selected item to save time in the loop
$hLastSelected = 0

While 1

    Switch GUIGetMsg()
        Case $GUI_EVENT_CLOSE
            Exit
        Case $hSet
            _Set_All()
        Case $hClear
            _Set_All(False) ; See the function code to see why we need to specify here and not in teh call above
    EndSwitch

    ; Get selected item
    $hSelected = _GUICtrlTreeView_GetSelection($hTV)

    ; Has it changed - we only need to get the index if it has
    If $hSelected <> $hLastSelected Then
        ; Get index of the newly selected item
        $iSelectedIndex = _ArraySearch($aItems, $hSelected)
        ; And save new selection
        $hLastSelected = $hSelected
    EndIf

    ; Now we check if the selected item check state matches the stored version
    If _GUICtrlTreeView_GetChecked($hTV, $hSelected) <> $aItems[$iSelectedIndex][1] Then

        ; If not we set the array to match so we do not repeat this on each pass
        $aItems[$iSelectedIndex][1] = _GUICtrlTreeView_GetChecked($hTV, $hSelected)

        ; And now we check/uncheck the related checkboxes
        Switch $aItems[$iSelectedIndex][1]
            Case True
                ; If checked then check the parents
                _Check_Parents($hSelected)
            Case False
                ; Or uncheck the children
                _Uncheck_Children($hSelected)
        EndSwitch
    EndIf

WEnd

Func _Check_Parents($hHandle)

    ; Get the handle of the parent
    $hParent = _GUICtrlTreeView_GetParentHandle($hTV, $hHandle)
    ; If there is no parent
    If $hParent = 0 Then
        Return
    EndIf
    ; Check the parent
    _GUICtrlTreeView_SetChecked($hTV, $hParent)
    ; Adjust the array
    $iIndex = _ArraySearch($aItems, $hParent)
    $aItems[$iIndex][1] = True
    ; And look for the grandparent and so on
    _Check_Parents($hParent)

EndFunc

Func _Uncheck_Children($hHandle)

    ; Get the handle of the first child
    $hChild = _GUICtrlTreeView_GetFirstChild($hTV, $hHandle)
    ; If there is no child
    If $hChild = 0 Then
        Return
    EndIf
    ; Uncheck the child
    _GUICtrlTreeView_SetChecked($hTV, $hChild, False)
    ; Adjust the array
    $iIndex = _ArraySearch($aItems, $hChild)
    $aItems[$iIndex][1] = False
    ; Check for children
    _Uncheck_Children($hChild)

    ; Now look for all grandchildren
    While 1
        ; Look for next child
        $hChild = _GUICtrlTreeView_GetNextChild($hTV, $hChild)
        ; Exit the loop if none found
        If $hChild = 0 Then
            ExitLoop
        EndIf
        ; Uncheck the child
        _GUICtrlTreeView_SetChecked($hTV, $hChild, False)
        ; Adjust the array
        $iIndex = _ArraySearch($aItems, $hChild)
        $aItems[$iIndex][1] = False
        ; Check for children
        _Uncheck_Children($hChild)
        ; And then look for the next child
    WEnd

EndFunc

Func _Set_All($fState = True) ; This means that the value is True unless we set it otherwise when we call the function

    ; Loop through the array and set the checkboxes
    For $i = 1 To UBound($aItems) - 1
        _GUICtrlTreeView_SetChecked($hTV, $aItems[$i][0], $fState)
    Next

EndFunc

I also added a pair of Set/Clear All buttons for you. :)

I hope you can follow it all - please ask if not. :graduated:

M23

P.S. And stop apologising for being new - we all were at some time! ;)

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

Morning M23,

I've been sat playing with this for a while now and i can't get it to work i'm sad to say. I understand what it's doing but i've hit a problem. Theres nothing wrong with what you've wrote above but i've been using the idea and writing what i want to happen in to my own script. The problem comes from this:

; Has it changed - we only need to get the index if it has
  If $hSelected <> $hLastSelected Then
   ; Get index of the newly selected item
   $iSelectedIndex = _ArraySearch($ItemsArray, $hSelected)
   ; And save new selection
   $hLastSelected = $hSelected
  EndIf

The $iSelectedIndex seems to be -1 for me which when it reaches the IF comparison line, falls over. I'm guessing a result of -1 means it didn't find what it was looking for in the Array it searched?

I must admit, i've done something different but i don't see how it would cause this problem. Where you have used variables for each entry in to the treeview, i have used an array of [x][3] and then done the following (this is because i didn't want to 'local' loads of variables i didn't plan on using after):

$tvItems= GUICtrlCreateTreeView(8, 16, 241, 305, BitOR($GUI_SS_DEFAULT_TREEVIEW, $TVS_CHECKBOXES), _
    $WS_EX_DLGMODALFRAME+$WS_EX_CLIENTEDGE)
    $hTV = GUICtrlGetHandle(-1)
 
    $ItemsArray[1][2] = GUICtrlCreateTreeViewItem("Food", $tvItems)
    $ItemsArray[1][0] = GuiCtrlGetHandle($ItemsArray[1][2])
    $ItemsArray[2][2] = GUICtrlCreateTreeViewItem("Drink", $tvItems)
    $ItemsArray[2][0] = GuiCtrlGetHandle($ItemsArray[2][2])
    $ItemsArray[3][2] = GUICtrlCreateTreeViewItem("Meat", $ItemsArray[1][2])
    $ItemsArray[3][0] = GuiCtrlGetHandle($ItemsArray[3][2])

Nothing else talks to the [x][2] part of the array so i don't see how it would cause an issue. In case it's an issue with where i declare variables (Because i'm using a MessageLoop function rather than the mainline of the code. The mainline just calls MessageLoop) i've placed all the ones involved as globals but that doesn't change the result.

I think the more i type the more i confuse the situation so, if you want more information i can provide it! I'm just fustrating myself cause i can't understand why it wouldn't find something in the array when i've done a messagebox to output the numbers of $hSelected and $hLastSelected and they come back with, what look like meaningful memory locations.

Link to comment
Share on other sites

  • Moderators

ndw,

I was tempted to put everything in the same array yesterday, but I thought it would confuse the issue! :)

I have altered the code I posted yesterday to reflect what you have changed and it works fine for me. Try comparing this script with what you have and see if you can see where you have gone wrong: :graduated:

#include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>
#Include <GuiTreeView.au3>
#include <Array.au3>

; Create an array to hold the handles and checkstate of the treeview items
Global $aItems[17][3]

$winGUI = GUICreate("Food_Drink", 500, 500)

$tvItems = GUICtrlCreateTreeView(8, 16, 241, 305, BitOR($GUI_SS_DEFAULT_TREEVIEW, $TVS_CHECKBOXES), _
    $WS_EX_DLGMODALFRAME+$WS_EX_CLIENTEDGE)
    $hTV = GUICtrlGetHandle(-1) ; Get handle of the control - works better in the UDF commands used later on
$aItems[0][2] = GUICtrlCreateTreeViewItem("Food", $tvItems)
$aItems[0][0] = GuiCtrlGetHandle($aItems[0][2]) ; Set the [n][0] element to the handle of the item
$aItems[1][2] = GUICtrlCreateTreeViewItem("Fruit", $aItems[0][2])
$aItems[1][0] = GuiCtrlGetHandle($aItems[1][2])
$aItems[2][2] = GUICtrlCreateTreeViewItem("Apple", $aItems[1][2])
$aItems[2][0] = GuiCtrlGetHandle($aItems[2][2])
$aItems[3][2] = GUICtrlCreateTreeViewItem("Meat", $aItems[0][2])
$aItems[3][0] = GuiCtrlGetHandle($aItems[3][2])
$aItems[4][2] = GUICtrlCreateTreeViewItem("Steak", $aItems[3][2])
$aItems[4][0] = GuiCtrlGetHandle($aItems[4][2])
$aItems[5][2] = GUICtrlCreateTreeViewItem("Chicken", $aItems[3][2])
$aItems[5][0] = GuiCtrlGetHandle($aItems[5][2])
$aItems[6][2] = GUICtrlCreateTreeViewItem("Dairy", $aItems[0][2])
$aItems[6][0] = GuiCtrlGetHandle($aItems[6][2])
$aItems[7][2] = GUICtrlCreateTreeViewItem("Cheese", $aItems[6][2])
$aItems[7][0] = GuiCtrlGetHandle($aItems[7][2])
$aItems[8][2] = GUICtrlCreateTreeViewItem("Drinks", $tvItems)
$aItems[8][0] = GuiCtrlGetHandle($aItems[8][2])
$aItems[9][2] = GUICtrlCreateTreeViewItem("Water", $aItems[8][2])
$aItems[9][0] = GuiCtrlGetHandle($aItems[9][2])
$aItems[10][2] = GUICtrlCreateTreeViewItem("Fizzy", $aItems[8][2])
$aItems[10][0] = GuiCtrlGetHandle($aItems[10][2])
$aItems[11][2] = GUICtrlCreateTreeViewItem("Cola", $aItems[10][2])
$aItems[11][0] = GuiCtrlGetHandle($aItems[11][2])
$aItems[12][2] = GUICtrlCreateTreeViewItem("Juice", $aItems[8][2])
$aItems[12][0] = GuiCtrlGetHandle($aItems[12][2])
$aItems[13][2] = GUICtrlCreateTreeViewItem("OrangeJuice", $aItems[12][2])
$aItems[13][0] = GuiCtrlGetHandle($aItems[13][2])
$aItems[14][2] = GUICtrlCreateTreeViewItem("Hot Drinks", $aItems[8][2])
$aItems[14][0] = GuiCtrlGetHandle($aItems[14][2])
$aItems[15][2] = GUICtrlCreateTreeViewItem("Tea", $aItems[14][2])
$aItems[15][0] = GuiCtrlGetHandle($aItems[15][2])
$aItems[16][2] = GUICtrlCreateTreeViewItem("Coffee", $aItems[14][2])
$aItems[16][0] = GuiCtrlGetHandle($aItems[16][2])

; Create buttons to set/clear all
$hSet = GUICtrlCreateButton("Set All", 300, 10, 80, 30)
$hClear = GUICtrlCreateButton("Clear All", 300, 50, 80, 30)

GUISetState()

; This will store the last selected item to save time in the loop
$hLastSelected = 0

While 1

    Switch GUIGetMsg()
        Case $GUI_EVENT_CLOSE
            Exit
        Case $hSet
            _Set_All()
        Case $hClear
            _Set_All(False) ; See the function code to see why we need to specify here and not in teh call above
    EndSwitch

    ; Get selected item
    $hSelected = _GUICtrlTreeView_GetSelection($hTV)

    ; Has it changed - we only need to get the index if it has
    If $hSelected <> $hLastSelected Then
        ; Get index of the newly selected item
        $iSelectedIndex = _ArraySearch($aItems, $hSelected)
        ; And save new selection
        $hLastSelected = $hSelected
    EndIf

    ; Now we check if the selected item check state matches the stored version
    If _GUICtrlTreeView_GetChecked($hTV, $hSelected) <> $aItems[$iSelectedIndex][1] Then

        ; If not we set the array to match so we do not repeat this on each pass
        $aItems[$iSelectedIndex][1] = _GUICtrlTreeView_GetChecked($hTV, $hSelected)

        ; And now we check/uncheck the related checkboxes
        Switch $aItems[$iSelectedIndex][1]
            Case True
                ; If checked then check the parents
                _Check_Parents($hSelected)
            Case False
                ; Or uncheck the children
                _Uncheck_Children($hSelected)
        EndSwitch
    EndIf

WEnd

Func _Check_Parents($hHandle)

    ; Get the handle of the parent
    $hParent = _GUICtrlTreeView_GetParentHandle($hTV, $hHandle)
    ; If there is no parent
    If $hParent = 0 Then
        Return
    EndIf
    ; Check the parent
    _GUICtrlTreeView_SetChecked($hTV, $hParent)
    ; Adjust the array
    $iIndex = _ArraySearch($aItems, $hParent)
    $aItems[$iIndex][1] = True
    ; And look for the grandparent and so on
    _Check_Parents($hParent)

EndFunc

Func _Uncheck_Children($hHandle)

    ; Get the handle of the first child
    $hChild = _GUICtrlTreeView_GetFirstChild($hTV, $hHandle)
    ; If there is no child
    If $hChild = 0 Then
        Return
    EndIf
    ; Uncheck the child
    _GUICtrlTreeView_SetChecked($hTV, $hChild, False)
    ; Adjust the array
    $iIndex = _ArraySearch($aItems, $hChild)
    $aItems[$iIndex][1] = False
    ; Check for children
    _Uncheck_Children($hChild)

    ; Now look for all grandchildren
    While 1
        ; Look for next child
        $hChild = _GUICtrlTreeView_GetNextChild($hTV, $hChild)
        ; Exit the loop if none found
        If $hChild = 0 Then
            ExitLoop
        EndIf
        ; Uncheck the child
        _GUICtrlTreeView_SetChecked($hTV, $hChild, False)
        ; Adjust the array
        $iIndex = _ArraySearch($aItems, $hChild)
        $aItems[$iIndex][1] = False
        ; Check for children
        _Uncheck_Children($hChild)
        ; And then look for the next child
    WEnd

EndFunc

Func _Set_All($fState = True) ; This means that the value is True unless we set it otherwise when we call the function

    ; Loop through the array and set the checkboxes
    For $i = 1 To UBound($aItems) - 1
        _GUICtrlTreeView_SetChecked($hTV, $aItems[$i][0], $fState)
    Next

EndFunc

Do come back if you still have problems - or if this code does not run correctly for you. ;)

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

*facepalm* I've found it. Before hand i'd got the select all to work through "$selectAll = GUICtrlCreateTreeViewItem("Select all", $tvTests)" with some script somewhere to handle it. I didn't remove this statement so when it went looking through the array, shock horror, it couldn't find a "Select All" and therefore output the -1. I knew it would be something stupid!

The whole thing works perfectly now with a select all, clear all, check with parents and uncheck children. Thank you very much for your help and i hope this thread helps others in the future :graduated:

Link to comment
Share on other sites

Hello, just a small update on this. I discovered a problem if i was to hit "Set All" right at the beginning then try and untick a parent. This does not untick the children the first time. I fixed this by adding the following to the Set All function.

Func _Set_All($fState = True) ; This means that the value is True unless we set it otherwise when we call the function
    ; Loop through the array and set the checkboxes
    For $i = 0 To UBound($aItems) - 1
        _GUICtrlTreeView_SetChecked($hTV, $aItems[$i][0], $fState)
        $aItems[$i][1] = $fState ; This goes through the awway and sets the checked value
    Next
EndFunc

There is also another tiny thing where Set All doesn't tick the first item. I fixed this by changing the For loop to start from 0.

Edited by ndw
Link to comment
Share on other sites

  • 3 years later...

Hello,

Thanks for the code. It works from child to parent - but I would like to have the "child check boxes" checked at the same time the "parent" is checked and also have the "child boxes" unchecked at the same time the parent is unchecked. In other words just checking and unchecking the parent.

Thanks

Edited by jreedmx
Link to comment
Share on other sites

  • Moderators

jreedmx,

Welcome to the AutoIt forums. :)

We normally expect you to make some effort as we tend not to produce code to order. Think of the old saying: "Give a man a fish, you feed him for a day; give a man a net and you feed him forever" - we try to be net makers and repairers, not fishmongers. ;)

But as this old code of mine can be improved enormously, I will see what I can do. However, as we have 40-odd guests arriving for "galette des rois" this afternoon, I suggest that you do not hold your breath! :D

M23

Edited by Melba23
Typo

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

  • Moderators

jreedmx,

Ten minutes before the gannets arrive - just time to post this much improved version which I worked on during gaps in my busy wife-imposed schedule this morning: :D

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

; Create flag to indicate TV item selection change
Global $hTVItemSelected = False
; Create array to hold TV item data
Global $aItems[17][3]

; Create GUI
Global $hGUI = GUICreate("Test", 500, 500)

; Create TreeView
Global $cTV = GUICtrlCreateTreeView(10, 10, 250, 350, BitOR($GUI_SS_DEFAULT_TREEVIEW, $TVS_CHECKBOXES))

; Fill TreeView
$aItems[0][2]  = GUICtrlCreateTreeViewItem("Food",         $cTV)
$aItems[1][2]  = GUICtrlCreateTreeViewItem("Fruit",        $aItems[0][2])
$aItems[2][2]  = GUICtrlCreateTreeViewItem("Apple",        $aItems[1][2])
$aItems[3][2]  = GUICtrlCreateTreeViewItem("Meat",         $aItems[0][2])
$aItems[4][2]  = GUICtrlCreateTreeViewItem("Steak",        $aItems[3][2])
$aItems[5][2]  = GUICtrlCreateTreeViewItem("Chicken",      $aItems[3][2])
$aItems[6][2]  = GUICtrlCreateTreeViewItem("Dairy",        $aItems[0][2])
$aItems[7][2]  = GUICtrlCreateTreeViewItem("Cheese",       $aItems[6][2])
$aItems[8][2]  = GUICtrlCreateTreeViewItem("Drinks",       $cTV)
$aItems[9][2]  = GUICtrlCreateTreeViewItem("Water",        $aItems[8][2])
$aItems[10][2] = GUICtrlCreateTreeViewItem("Fizzy",        $aItems[8][2])
$aItems[11][2] = GUICtrlCreateTreeViewItem("Cola",         $aItems[10][2])
$aItems[12][2] = GUICtrlCreateTreeViewItem("Juice",        $aItems[8][2])
$aItems[13][2] = GUICtrlCreateTreeViewItem("Orange Juice", $aItems[12][2])
$aItems[14][2] = GUICtrlCreateTreeViewItem("Hot Drinks",   $aItems[8][2])
$aItems[15][2] = GUICtrlCreateTreeViewItem("Tea",          $aItems[14][2])
$aItems[16][2] = GUICtrlCreateTreeViewItem("Coffee",       $aItems[14][2])

; Set initial unchecked state and get item handles (needed for later code)
For $i = 0 To UBound($aItems) - 1
    $aItems[$i][1] = False
    $aItems[$i][0] = GUICtrlGetHandle($aItems[$i][2])
Next

; Expand TreeView
_GUICtrlTreeView_Expand($cTV)

; Create buttons to set/clear all items
Global $cSet = GUICtrlCreateButton("Set All", 300, 10, 80, 30)
Global $cClear = GUICtrlCreateButton("Clear All", 300, 50, 80, 30)

GUISetState()

; Register message to look for TV item selection change
GUIRegisterMsg($WM_NOTIFY, "_WM_NOTIFY")

Global $bState, $iItemIndex
While 1

    Switch GUIGetMsg()
        Case $GUI_EVENT_CLOSE
            Exit
        Case $cSet
            _Adjust_All()
        Case $cClear
            _Adjust_All(False)
    EndSwitch

    ; An item has been selected
    If $hTVItemSelected Then
        ; Determine checked state
        $bState = _GUICtrlTreeView_GetChecked($cTV, $hTVItemSelected)
        ; Find item in array
        $iItemIndex = _ArraySearch($aItems, $hTVItemSelected)
        ; If checked state has altered
        If $aItems[$iItemIndex][1] <> $bState Then
            ; Store new state
            $aItems[$iItemIndex][1] = $bState
            ; Adjust parents and children as required
            _Adjust_Parents($hTVItemSelected, $bState)
            _Adjust_Children($hTVItemSelected, $bState)
        EndIf
        ; Clear flag
        $hTVItemSelected = 0
    EndIf

WEnd

Func _Adjust_All($bState = True)

    ; Loop through items
    For $i = 0 To UBound($aItems) - 1
        ; Adjust item
        _GUICtrlTreeView_SetChecked($cTV, $aItems[$i][0], $bState)
        ; Adjust array
        $aItems[$i][1] = $bState
    Next

EndFunc   ;==>_Adjust_All

Func _Adjust_Parents($hPassedItem, $bState = True)

    Local $iIndex

    ; Get the handle of the parent
    Local $hParent = _GUICtrlTreeView_GetParentHandle($cTV, $hPassedItem)
    If $hParent = 0 Then Return
    ; Assume parent is to be adjusted
    Local $bAdjustParent = True
    ; Need to confirm all siblings clear before clearing parent
    If $bState = False Then
        ; Check on number of siblings
        Local $iCount = _GUICtrlTreeView_GetChildCount($cTV, $hParent)
        ; If only 1 sibling then parent can be cleared - if more then need to look at them all
        If $iCount <> 1 Then
            ; Number of siblings checked
            Local $iCheckCount = 0
            ; Move through previous siblings
            Local $hSibling = $hPassedItem
            While 1
                $hSibling = _GUICtrlTreeView_GetPrevSibling($cTV, $hSibling)
                ; If found
                If $hSibling Then
                    ; Is sibling checked)
                    If _GUICtrlTreeView_GetChecked($cTV, $hSibling) Then
                        ; Increase count if so
                        $iCheckCount += 1
                    EndIf
                Else
                    ; No point in continuing
                    ExitLoop
                EndIf
            WEnd
            ; Move through later siblings
            $hSibling = $hPassedItem
            While 1
                $hSibling = _GUICtrlTreeView_GetNextSibling($cTV, $hSibling)
                If $hSibling Then
                    If _GUICtrlTreeView_GetChecked($cTV, $hSibling) Then
                        $iCheckCount += 1
                    EndIf
                Else
                    ExitLoop
                EndIf
            WEnd
            ; If at least one sibling checked then do not clear parent
            If $iCheckCount Then $bAdjustParent = False
        EndIf
    EndIf
    ; If parent is to be adjusted
    If $bAdjustParent Then
        ; Adjust the array
        $iIndex = _ArraySearch($aItems, $hParent)
        If @error Then Return
        $aItems[$iIndex][1] = $bState
        ; Adjust the parent
        _GUICtrlTreeView_SetChecked($cTV, $hParent, $bState)
        ; And now do the same for the generation above
        _Adjust_Parents($hParent, $bState)
    EndIf

EndFunc   ;==>_Check_Parents

Func _Adjust_Children($hPassedItem, $bState = True)

    Local $iIndex

    ; Get the handle of the first child
    Local $hChild = _GUICtrlTreeView_GetFirstChild($cTV, $hPassedItem)
    If $hChild = 0 Then Return
    ; Loop through children
    While 1
        ; Adjust the array
        $iIndex = _ArraySearch($aItems, $hChild)
        If @error Then Return
        $aItems[$iIndex][1] = $bState
        ; Adjust the child
        _GUICtrlTreeView_SetChecked($cTV, $hChild, $bState)
        ; And now do the same for the generation beow
        _Adjust_Children($hChild, $bState)
        ; Now get next child
        $hChild = _GUICtrlTreeView_GetNextChild($cTV, $hChild)
        ; Exit the loop if no more found
        If $hChild = 0 Then ExitLoop
    WEnd

EndFunc   ;==>_Adjust_Children

Func _WM_NOTIFY($hWnd, $iMsg, $wParam, $lParam)

    #forceref $hWnd, $iMsg, $wParam
    ; Create NMTREEVIEW structure
    Local $tStruct = DllStructCreate("struct;hwnd hWndFrom;uint_ptr IDFrom;INT Code;endstruct;" & _
            "uint Action;struct;uint OldMask;handle OldhItem;uint OldState;uint OldStateMask;" & _
            "ptr OldText;int OldTextMax;int OldImage;int OldSelectedImage;int OldChildren;lparam OldParam;endstruct;" & _
            "struct;uint NewMask;handle NewhItem;uint NewState;uint NewStateMask;" & _
            "ptr NewText;int NewTextMax;int NewImage;int NewSelectedImage;int NewChildren;lparam NewParam;endstruct;" & _
            "struct;long PointX;long PointY;endstruct", $lParam)
    Local $hWndFrom = DllStructGetData($tStruct, "hWndFrom")
    If $hWndFrom = GUICtrlGetHandle($cTV) Then
        Switch  DllStructGetData($tStruct, "Code")
            Case $TVN_SELCHANGEDA, $TVN_SELCHANGEDW
                Local $hItem = DllStructGetData($tStruct, "NewhItem")
                ; Set flag to selected item handle
                If $hItem Then $hTVItemSelected = $hItem
        EndSwitch
    EndIf
EndFunc
I have not had much time to test it throughly - so if anyone else wants to try, feel free. But do not expect any replies for the next few hours - I will be on tea/coffee serving duties. :(>

M23

Edited by Melba23
Typo

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

  • Moderators

jreedmx,

I have rewritten the checkbox adjusting code as a UDF - see here. :)

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

  • 2 weeks later...

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...