kinch Posted June 8, 2014 Share Posted June 8, 2014 Hi guys, Sorry for such a trivial post, but this is really doing my head in. I've spent all day trying to figure this out and the last 3 hours searching everything on this forum that mentions "treeview". I'm trying to build a Treeview based on variable input data. The problem is that some of the data is duplicated, and I can't figure out how to avoid creating duplicate children in the treeview. Code: expandcollapse popup#include <GUIConstantsEx.au3> #include <WindowsConstants.au3> #include <TreeViewConstants.au3> #include <GuiTreeView.au3> $a = GUICreate("My GUI with treeview", 700, 315) Global $treeview = GUICtrlCreateTreeView(6, 6, 338, 303, BitOR($TVS_HASBUTTONS, $TVS_HASLINES, $TVS_LINESATROOT, $TVS_DISABLEDRAGDROP, $TVS_SHOWSELALWAYS), $WS_EX_CLIENTEDGE) Build("Apps|WordPerfect") Build("Apps|Word") Build("Apps|Outlook") Build("Apps|Outlook|Addins") Build("Training|Outlook") Func Build($input) Local $child Local $items = StringSplit($input, "|") For $i = 1 To $items[0] If ($i > 1) Then ; child item $child = _GUICtrlTreeView_AddChild($treeview, $child, $items[$i]) Else ; root item $child = _GUICtrlTreeView_Add($treeview, 1, $items[$i]) EndIf Next EndFunc ;==>Build ; Output that I want it to look like, based on the above "input". Global $treeview2 = GUICtrlCreateTreeView(350, 6, 338, 303, BitOR($TVS_HASBUTTONS, $TVS_HASLINES, $TVS_LINESATROOT, $TVS_DISABLEDRAGDROP, $TVS_SHOWSELALWAYS), $WS_EX_CLIENTEDGE) $apps = _GUICtrlTreeView_Add($treeview2, "", "Apps") _GUICtrlTreeView_AddChild($treeview2, $apps, "WordPerfect") _GUICtrlTreeView_AddChild($treeview2, $apps, "Word") $outlook = _GUICtrlTreeView_AddChild($treeview2, $apps, "Outlook") _GUICtrlTreeView_AddChild($treeview2, $outlook, "Addins") $training = _GUICtrlTreeView_Add($treeview2, "", "Training") _GUICtrlTreeView_AddChild($treeview2, $training, "Outlook") GUISetState(@SW_SHOW) While (1) $nmsg = GUIGetMsg() Switch $nmsg Case $GUI_EVENT_CLOSE Exit EndSwitch WEnd The Treeview on the left is what my "build" code creates. The Treeview on the right is what I want it to look like, based on the string input I provided to the Build function. In other words, the Treeview shouldn't just blindly create a new element, but should check for an existing one of the same name. If it exists, then it drills down into that sub-tree, and then repeats the same process. I've investigated the FindItem function, but that doesn't help since it searches the entire treeview, and it might find an item under the wrong heading (ie. Outlook might be found under Apps, when I'm trying to search under Training). I looked into FindItemEx, but that gets complicated with the 4th Input (ie. Apps/Outlook would exist, but the FindEx would fail on Apps/Outlook/Addins). Every solution I've tried of listing the children of a node to see if one already exists fails. I think a further complication that I'm struggling with is the difference between a ControlID and a Handle. The other thing I'll mention is that I can't use variables for each "group" like in the working example, as the input will eventually contain hundreds of lines with many duplicates. It's doing my head in, no matter what ideas I try, it doesn't produce the right output. I'm sure it can't be that complicated, but I'm just at the end of my patience with this. Please, if anyone can provide some guidance, it'll stop me from screaming in frustration. Link to comment Share on other sites More sharing options...
Moderators Melba23 Posted June 8, 2014 Moderators Share Posted June 8, 2014 kinch,If you are prepared to add a couple of lines to create the first level items then this code works: expandcollapse popup#include <GUIConstantsEx.au3> #include <Array.au3> #include <GuiTreeView.au3> ; Array to hold item titles and ControlIDs Global $aTreeViewItem[2][2] = [[1, 0], ["", 0]] $hGUI = GUICreate("Test", 500, 500) $aTreeViewItem[1][1] = GUICtrlCreateTreeView(10, 10, 480, 380) GUISetState() _Build("Apps") ; Base level item - needed _Build("Apps|WordPerfect") _Build("Apps|Word") _Build("Apps|Outlook") _Build("Apps|Outlook") ; Duplicate for test _Build("Apps|Outlook|Addins") _Build("Training") ; Base level item - needed _Build("Training|Outlook") While 1 Switch GUIGetMsg() Case $GUI_EVENT_CLOSE Exit EndSwitch WEnd Func _Build($sString) If _ArraySearch($aTreeViewItem, $sString, 1) <> -1 Then ; Duplicate Return EndIf ; Split path $aSplit = StringSplit($sString, "|") ; Look for path removing one leyer each time For $i = $aSplit[0] To 1 Step -1 ; This is the path we are looking for this time $sPattern = "" ; Build it up one layer at a time For $j = 1 To $i - 1 $sPattern &= $aSplit[$j] & "|" Next ; Remove final "|" $sPattern = StringTrimRight($sPattern, 1) ; Is this path already in the treeview? $iIndex = _ArraySearch($aTreeViewItem, $sPattern, 1) ; If so then exit loop If $iIndex Then ExitLoop Next ; Add an element to the array $aTreeViewItem[0][0] += 1 ReDim $aTreeViewItem[$aTreeViewItem[0][0] + 1][2] ; Save the path $aTreeViewItem[$aTreeViewItem[0][0]][0] = $sString ; Get the title to add $sTitle = $sString If $sPattern Then $sTitle = StringReplace($sString, $sPattern & "|", "") If $iIndex = -1 Then ; Add at root if nothing found $aTreeViewItem[$aTreeViewItem[0][0]][1] = GUICtrlCreateTreeViewItem($sTitle, $aTreeViewItem[1][1]) Else ; Or add to found path $aTreeViewItem[$aTreeViewItem[0][0]][1] = GUICtrlCreateTreeViewItem($sTitle, $aTreeViewItem[$iIndex][1]) EndIf ; Expand any newly create branches _GUICtrlTreeView_Expand($aTreeViewItem[1][1]) EndFunc ;==>_BuildI hope the comments are clear enough - 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 Link to comment Share on other sites More sharing options...
Moderators Melba23 Posted June 8, 2014 Moderators Share Posted June 8, 2014 kinch,After a bit more thought, here is a version which works with your original strings: expandcollapse popup#include <GUIConstantsEx.au3> #include <Array.au3> #include <GuiTreeView.au3> Global $aTreeViewItem[2][2] = [[1, 0], ["", 0]] $hGUI = GUICreate("Test", 500, 500) $aTreeViewItem[1][1] = GUICtrlCreateTreeView(10, 10, 480, 380) GUISetState() _Build("Apps|WordPerfect") _Build("Apps|Word") _Build("Apps|Outlook") _Build("Apps|Outlook") ; Duplicate for check _Build("Apps|Outlook|Addins") _Build("Training|Outlook") While 1 Switch GUIGetMsg() Case $GUI_EVENT_CLOSE Exit EndSwitch WEnd Func _Build($sString) If _ArraySearch($aTreeViewItem, $sString, 1) <> -1 Then ; Duplicate Return EndIf ; Split path $aSplit = StringSplit($sString, "|") ; Check if base level exists and create if not If _ArraySearch($aTreeViewItem, $aSplit[1], 1) = -1 Then ; Add an element to the array $aTreeViewItem[0][0] += 1 ReDim $aTreeViewItem[$aTreeViewItem[0][0] + 1][2] ; Save the name $aTreeViewItem[$aTreeViewItem[0][0]][0] = $aSplit[1] ; Add at root $aTreeViewItem[$aTreeViewItem[0][0]][1] = GUICtrlCreateTreeViewItem($aSplit[1], $aTreeViewItem[1][1]) EndIf ; Look for string removing one leyer each time For $i = $aSplit[0] To 1 Step -1 ; This is the path we are looking for this time $sPattern = "" ; Build it up one layer at a time For $j = 1 To $i - 1 $sPattern &= $aSplit[$j] & "|" Next ; Remove final "|" $sPattern = StringTrimRight($sPattern, 1) ; Is this path already in the treeview? $iIndex = _ArraySearch($aTreeViewItem, $sPattern, 1) ; If so then exit loop If $iIndex Then ExitLoop Next ; Add an element to the array $aTreeViewItem[0][0] += 1 ReDim $aTreeViewItem[$aTreeViewItem[0][0] + 1][2] ; Save the path $aTreeViewItem[$aTreeViewItem[0][0]][0] = $sString ; Get the title to add $sTitle = $sString If $sPattern Then $sTitle = StringReplace($sString, $sPattern & "|", "") If $iIndex = -1 Then ; Add at root if nothing found $aTreeViewItem[$aTreeViewItem[0][0]][1] = GUICtrlCreateTreeViewItem($sTitle, $aTreeViewItem[1][1]) Else ; Or add to found path $aTreeViewItem[$aTreeViewItem[0][0]][1] = GUICtrlCreateTreeViewItem($sTitle, $aTreeViewItem[$iIndex][1]) EndIf _GUICtrlTreeView_Expand($aTreeViewItem[1][1]) EndFunc ;==>_BuildI must admit to being quite pleased with it. Again, please ask if you have any questions. 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 Link to comment Share on other sites More sharing options...
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