ndw Posted September 19, 2011 Posted September 19, 2011 Good afternoon, I am new to AutoIt and the forums so, hello 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)
Moderators Melba23 Posted September 19, 2011 Moderators Posted September 19, 2011 ndw, Welcome to the AutoIt forum. 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: expandcollapse popup#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 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 columnsChooseFileFolder ---- Single and multiple selections from specified path treeview listingDate_Time_Convert -- Easily convert date/time formats, including the language usedExtMsgBox --------- A highly customisable replacement for MsgBoxGUIExtender -------- Extend and retract multiple sections within a GUIGUIFrame ---------- Subdivide GUIs into many adjustable framesGUIListViewEx ------- Insert, delete, move, drag, sort, edit and colour ListView itemsGUITreeViewEx ------ Check/clear parent and child checkboxes in a TreeViewMarquee ----------- Scrolling tickertape GUIsNoFocusLines ------- Remove the dotted focus lines from buttons, sliders, radios and checkboxesNotify ------------- Small notifications on the edge of the displayScrollbars ----------Automatically sized scrollbars with a single commandStringSize ---------- Automatically size controls to fit textToast -------------- Small GUIs which pop out of the notification area
ndw Posted September 19, 2011 Author Posted September 19, 2011 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?
Moderators Melba23 Posted September 19, 2011 Moderators Posted September 19, 2011 ndw,When used in this contect, -1 is shorthand for "the last control created". M23 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 columnsChooseFileFolder ---- Single and multiple selections from specified path treeview listingDate_Time_Convert -- Easily convert date/time formats, including the language usedExtMsgBox --------- A highly customisable replacement for MsgBoxGUIExtender -------- Extend and retract multiple sections within a GUIGUIFrame ---------- Subdivide GUIs into many adjustable framesGUIListViewEx ------- Insert, delete, move, drag, sort, edit and colour ListView itemsGUITreeViewEx ------ Check/clear parent and child checkboxes in a TreeViewMarquee ----------- Scrolling tickertape GUIsNoFocusLines ------- Remove the dotted focus lines from buttons, sliders, radios and checkboxesNotify ------------- Small notifications on the edge of the displayScrollbars ----------Automatically sized scrollbars with a single commandStringSize ---------- Automatically size controls to fit textToast -------------- Small GUIs which pop out of the notification area
ndw Posted September 19, 2011 Author Posted September 19, 2011 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 Now to work on a Select All function but have an idea how to go about it!
ndw Posted September 19, 2011 Author Posted September 19, 2011 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?
Moderators Melba23 Posted September 19, 2011 Moderators Posted September 19, 2011 (edited) ndw,so if you were to have made the handle someplace else, you would have put "$hTV = GUICtrlGetHandle($tvItems)" in its place?Exactly! Now to work on a Select All functionI hope you are looking at arrays - here is a good tutorial to get you started. M23Edit: Tags again. Edited September 19, 2011 by Melba23 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 columnsChooseFileFolder ---- Single and multiple selections from specified path treeview listingDate_Time_Convert -- Easily convert date/time formats, including the language usedExtMsgBox --------- A highly customisable replacement for MsgBoxGUIExtender -------- Extend and retract multiple sections within a GUIGUIFrame ---------- Subdivide GUIs into many adjustable framesGUIListViewEx ------- Insert, delete, move, drag, sort, edit and colour ListView itemsGUITreeViewEx ------ Check/clear parent and child checkboxes in a TreeViewMarquee ----------- Scrolling tickertape GUIsNoFocusLines ------- Remove the dotted focus lines from buttons, sliders, radios and checkboxesNotify ------------- Small notifications on the edge of the displayScrollbars ----------Automatically sized scrollbars with a single commandStringSize ---------- Automatically size controls to fit textToast -------------- Small GUIs which pop out of the notification area
ndw Posted September 19, 2011 Author Posted September 19, 2011 Thank you again and i've swapped everything over to an array now and the Select All is working great 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!
Moderators Melba23 Posted September 19, 2011 Moderators Posted September 19, 2011 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: expandcollapse popup#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. M23 P.S. And stop apologising for being new - we all were at some time! 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 columnsChooseFileFolder ---- Single and multiple selections from specified path treeview listingDate_Time_Convert -- Easily convert date/time formats, including the language usedExtMsgBox --------- A highly customisable replacement for MsgBoxGUIExtender -------- Extend and retract multiple sections within a GUIGUIFrame ---------- Subdivide GUIs into many adjustable framesGUIListViewEx ------- Insert, delete, move, drag, sort, edit and colour ListView itemsGUITreeViewEx ------ Check/clear parent and child checkboxes in a TreeViewMarquee ----------- Scrolling tickertape GUIsNoFocusLines ------- Remove the dotted focus lines from buttons, sliders, radios and checkboxesNotify ------------- Small notifications on the edge of the displayScrollbars ----------Automatically sized scrollbars with a single commandStringSize ---------- Automatically size controls to fit textToast -------------- Small GUIs which pop out of the notification area
ndw Posted September 20, 2011 Author Posted September 20, 2011 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.
Moderators Melba23 Posted September 20, 2011 Moderators Posted September 20, 2011 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: expandcollapse popup#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 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 columnsChooseFileFolder ---- Single and multiple selections from specified path treeview listingDate_Time_Convert -- Easily convert date/time formats, including the language usedExtMsgBox --------- A highly customisable replacement for MsgBoxGUIExtender -------- Extend and retract multiple sections within a GUIGUIFrame ---------- Subdivide GUIs into many adjustable framesGUIListViewEx ------- Insert, delete, move, drag, sort, edit and colour ListView itemsGUITreeViewEx ------ Check/clear parent and child checkboxes in a TreeViewMarquee ----------- Scrolling tickertape GUIsNoFocusLines ------- Remove the dotted focus lines from buttons, sliders, radios and checkboxesNotify ------------- Small notifications on the edge of the displayScrollbars ----------Automatically sized scrollbars with a single commandStringSize ---------- Automatically size controls to fit textToast -------------- Small GUIs which pop out of the notification area
ndw Posted September 20, 2011 Author Posted September 20, 2011 *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
ndw Posted September 28, 2011 Author Posted September 28, 2011 (edited) 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 September 28, 2011 by ndw
jreedmx Posted January 3, 2015 Posted January 3, 2015 (edited) 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 January 3, 2015 by jreedmx
Moderators Melba23 Posted January 4, 2015 Moderators Posted January 4, 2015 (edited) 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! M23 Edited January 4, 2015 by Melba23 Typo 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 columnsChooseFileFolder ---- Single and multiple selections from specified path treeview listingDate_Time_Convert -- Easily convert date/time formats, including the language usedExtMsgBox --------- A highly customisable replacement for MsgBoxGUIExtender -------- Extend and retract multiple sections within a GUIGUIFrame ---------- Subdivide GUIs into many adjustable framesGUIListViewEx ------- Insert, delete, move, drag, sort, edit and colour ListView itemsGUITreeViewEx ------ Check/clear parent and child checkboxes in a TreeViewMarquee ----------- Scrolling tickertape GUIsNoFocusLines ------- Remove the dotted focus lines from buttons, sliders, radios and checkboxesNotify ------------- Small notifications on the edge of the displayScrollbars ----------Automatically sized scrollbars with a single commandStringSize ---------- Automatically size controls to fit textToast -------------- Small GUIs which pop out of the notification area
Moderators Melba23 Posted January 4, 2015 Moderators Posted January 4, 2015 (edited) 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: expandcollapse popup#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 EndFuncI 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 January 4, 2015 by Melba23 Typo jreedmx 1 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 columnsChooseFileFolder ---- Single and multiple selections from specified path treeview listingDate_Time_Convert -- Easily convert date/time formats, including the language usedExtMsgBox --------- A highly customisable replacement for MsgBoxGUIExtender -------- Extend and retract multiple sections within a GUIGUIFrame ---------- Subdivide GUIs into many adjustable framesGUIListViewEx ------- Insert, delete, move, drag, sort, edit and colour ListView itemsGUITreeViewEx ------ Check/clear parent and child checkboxes in a TreeViewMarquee ----------- Scrolling tickertape GUIsNoFocusLines ------- Remove the dotted focus lines from buttons, sliders, radios and checkboxesNotify ------------- Small notifications on the edge of the displayScrollbars ----------Automatically sized scrollbars with a single commandStringSize ---------- Automatically size controls to fit textToast -------------- Small GUIs which pop out of the notification area
jreedmx Posted January 4, 2015 Posted January 4, 2015 Melba23, Thanks for your quick response and the time and effort you put into creating the script. John
Moderators Melba23 Posted January 6, 2015 Moderators Posted January 6, 2015 jreedmx,I have rewritten the checkbox adjusting code as a UDF - see here. M23 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 columnsChooseFileFolder ---- Single and multiple selections from specified path treeview listingDate_Time_Convert -- Easily convert date/time formats, including the language usedExtMsgBox --------- A highly customisable replacement for MsgBoxGUIExtender -------- Extend and retract multiple sections within a GUIGUIFrame ---------- Subdivide GUIs into many adjustable framesGUIListViewEx ------- Insert, delete, move, drag, sort, edit and colour ListView itemsGUITreeViewEx ------ Check/clear parent and child checkboxes in a TreeViewMarquee ----------- Scrolling tickertape GUIsNoFocusLines ------- Remove the dotted focus lines from buttons, sliders, radios and checkboxesNotify ------------- Small notifications on the edge of the displayScrollbars ----------Automatically sized scrollbars with a single commandStringSize ---------- Automatically size controls to fit textToast -------------- Small GUIs which pop out of the notification area
afeen Posted January 15, 2015 Posted January 15, 2015 Melba's answer is ver'easy to understand. Thanks a lot melba, I can learnin' autoit script 1 by 1 B-cause your answers in every questions in this forum. (Indonesia)
Recommended Posts
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 accountSign in
Already have an account? Sign in here.
Sign In Now