Sign in to follow this  
Followers 0
fcg

Issue Returning Treeview Child and Parent info

5 posts in this topic

Hi,

I'm trying to return information from all the items that are checked in the treeview. I would like to return if the parent is checked and any children that are checked if the parent isnt checked, either postition (i.e Parent2|Child3|Sibling1 or 2,3,1) or text would work. Ive been trying various "_GUICtrlTree..." functions with little success.

Any direction would be greatly appreciated.

I did find this gem that automaticaly checks child items if the parent is selected. Much respect to Melba23 and Authenticity for that.

I've posted the code that I'm working on.

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

Local $hGUI, $Tree, $hTree, $hItems[40][2] = [[0]]
$Form1_1 = GUICreate("Form1", 616, 532, 192, 124)
$string = StringSplit("parent1,child1,child2,child3,sibling1,parent2,child1,child2,child3,sibling1",",")
$button1 = GUICtrlCreateButton("Select", 40, 200, 100, 50)
$List1 = GUICtrlCreateTreeView(40, 260, 530, 200, BitOR($GUI_SS_DEFAULT_TREEVIEW,$TVS_EDITLABELS,$TVS_CHECKBOXES), $WS_EX_CLIENTEDGE)
GUISetState(@SW_SHOW)
$hTree = GUICtrlGetHandle($List1)
$hImage = _GUIImageList_Create(16, 16, 5, 3)
    _GUIImageList_AddIcon($hImage, "shell32.dll", 8)
    _GUIImageList_AddIcon($hImage, "shell32.dll", 166)
    _GUICtrlTreeView_SetNormalImageList($List1, $hImage)
_GUICtrlTreeView_BeginUpdate($List1)
For $x = 0 To ubound($string) - 1
if StringInStr($string[$x],"parent",0) > 0 Then
$tree_disk = _GUICtrlTreeView_Add($List1, 0, $string[$x], 0)
EndIf
if StringInStr($string[$x],"child",0) > 0 Then
$tree_Part =  _GUICtrlTreeView_AddChild($List1, $tree_disk,$string[$x], 1,1)
EndIf
if StringInStr($string[$x],"sibling",0) > 0 Then
    $tree_logical =  _GUICtrlTreeView_AddChild($List1,$tree_Part, $string[$x], 1, 1)
EndIf
Next
   _GUICtrlTreeView_EndUpdate($List1)

GUIRegisterMsg($WM_NOTIFY, "_WM_NOTIFY")


While 1
    $nMsg = GUIGetMsg()
    Switch $nMsg
        Case $GUI_EVENT_CLOSE
            Exit
        Case $button1
            MsgBox(0,"",_GUICtrlTreeView_GetCount($hTree))
    EndSwitch
WEnd


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

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

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

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

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

                    EndIf
            EndSwitch
    EndSwitch
    Return $GUI_RUNDEFMSG
EndFunc

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

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

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

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

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

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

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

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

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

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

Share this post


Link to post
Share on other sites



Hi fcgnewbie,

If you can assume that checking an item means that all the items in the entire subbranch is checked (and it seems as if that is what you do) then I think this will do it.

#include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>
#include <TreeViewConstants.au3>
#include <GuiTreeView.au3>
#include <ButtonConstants.au3>
#include <Array.au3>
Local $hGUI, $Tree, $hTree, $hItems[40][2] = [[0]]
$Form1_1 = GUICreate("Form1", 616, 532, 192, 124)
$string = StringSplit("parent1,child1,child2,child3,sibling1,parent2,child1,child2,child3,sibling1",",")
$button1 = GUICtrlCreateButton("Select", 40, 200, 100, 50)
$List1 = GUICtrlCreateTreeView(40, 260, 530, 200, BitOR($GUI_SS_DEFAULT_TREEVIEW,$TVS_EDITLABELS,$TVS_CHECKBOXES), $WS_EX_CLIENTEDGE)
GUISetState(@SW_SHOW)
$hTree = GUICtrlGetHandle($List1)
$hImage = _GUIImageList_Create(16, 16, 5, 3)
    _GUIImageList_AddIcon($hImage, "shell32.dll", 8)
    _GUIImageList_AddIcon($hImage, "shell32.dll", 166)
    _GUICtrlTreeView_SetNormalImageList($List1, $hImage)
_GUICtrlTreeView_BeginUpdate($List1)
For $x = 0 To ubound($string) - 1
if StringInStr($string[$x],"parent",0) > 0 Then
$tree_disk = _GUICtrlTreeView_Add($List1, 0, $string[$x], 0)
EndIf
if StringInStr($string[$x],"child",0) > 0 Then
$tree_Part =  _GUICtrlTreeView_AddChild($List1, $tree_disk,$string[$x], 1,1)
EndIf
if StringInStr($string[$x],"sibling",0) > 0 Then
    $tree_logical =  _GUICtrlTreeView_AddChild($List1,$tree_Part, $string[$x], 1, 1)
EndIf
Next
   _GUICtrlTreeView_EndUpdate($List1)
GUIRegisterMsg($WM_NOTIFY, "_WM_NOTIFY")

While 1
    $nMsg = GUIGetMsg()
    Switch $nMsg
        Case $GUI_EVENT_CLOSE
            Exit
        Case $button1
      _ArrayDisplay( GetChecked(), "Checked items" )
            ;MsgBox(0,"",_GUICtrlTreeView_GetCount($hTree))
    EndSwitch
WEnd
Func GetChecked()
Local $item, $aArray[100], $iArray = 0
$item = _GUICtrlTreeView_GetFirstItem( $hTree )
While $item
  If _GUICtrlTreeView_GetChecked( $hTree, $item ) Then
   $aArray[$iArray] = "Checked: " & GetPath( $hTree, $item )
   $iArray += 1
   $item = GetNextItem( $hTree, $item )
   If $item Then
    $aArray[$iArray] = "Next to test: " & GetPath( $hTree, $item )
    $iArray += 1
   Else
    $aArray[$iArray] = "No more items to test"
    $iArray += 1
   EndIf
  Else
   $item = _GUICtrlTreeView_GetNext( $hTree, $item )
  EndIf
WEnd
If $iArray = 0 then
  $aArray[$iArray] = "No items checked"
  $iArray += 1
EndIf
ReDim $aArray[$iArray]
Return $aArray
EndFunc
Func GetPath( $hTV, $item )
Local $path = _GUICtrlTreeView_GetText( $hTV, $item )
Local $parent = _GUICtrlTreeView_GetParentHandle( $hTV, $item )
While $parent
  $path = _GUICtrlTreeView_GetText( $hTV, $parent ) & "|" & $path
  $parent = _GUICtrlTreeView_GetParentHandle( $hTV, $parent )
WEnd
Return $path
EndFunc
Func GetNextItem( $hTV, $subBranch )
; Find the first item outside this subbranch
Local $item = $subBranch, $nextItem = _GUICtrlTreeView_GetNextChild( $hTV, $item )
While Not $nextItem
  $item = _GUICtrlTreeView_GetParentHandle( $hTV, $item )  ; Parent item
  If Not $item Then ExitLoop                ; No more items
  $nextItem = _GUICtrlTreeView_GetNextChild( $hTV, $item ) ; Next item
WEnd
Return $nextItem
EndFunc
Func _WM_NOTIFY($hWnd, $iMsg, $iwParam, $ilParam)
    Local $hWndFrom, $iIDFrom, $iCode, $tNMHDR
    Local $iPos, $iX, $iY, $tPt, $iHitTest, $fWasChecked
    Local $hItem
    $tNMHDR = DllStructCreate($tagNMHDR, $ilParam)
    $hWndFrom = HWnd(DllStructGetData($tNMHDR, "hWndFrom"))
    $iIDFrom = DllStructGetData($tNMHDR, "IDFrom")
    $iCode = DllStructGetData($tNMHDR, "Code")
    Switch $hWndFrom
        Case $hTree
            Switch $iCode
                Case $NM_CLICK
                    $iPos = _WinAPI_GetMessagePos()
                    $iX = BitAND($iPos, 0xFFFF)
                    $iY = BitShift($iPos, 16)
                    $tPt = DllStructCreate($tagPOINT)
                    DllStructSetData($tPt, "X", $iX)
                    DllStructSetData($tPt, "Y", $iY)
                    _WinAPI_ScreenToClient($hTree, $tPt)
                    $iX = DllStructGetData($tPt, "X")
                    $iY = DllStructGetData($tPt, "Y")
                    $tTVHTInfo = _GUICtrlTreeView_HitTestEx($hTree, $iX, $iY)
                    If DllStructGetData($tTVHTInfo, "Flags") = $TVHT_ONITEMSTATEICON Then
                        $hItem = DllStructGetData($tTVHTInfo, "Item")
                        $fWasChecked = _GUICtrlTreeView_GetChecked($hTree, $hItem)
                        If $fWasChecked Then
                            _GUICtrlTreeView_BeginUpdate($hTree)
                            _Uncheck($hItem)
                            _GUICtrlTreeView_EndUpdate($hTree)
                        Else
                            _GUICtrlTreeView_BeginUpdate($hTree)
                            _CallItemFunc($hItem)
                            _Check($hItem)
                            _GUICtrlTreeView_EndUpdate($hTree)
                        EndIf
                    EndIf
            EndSwitch
    EndSwitch
    Return $GUI_RUNDEFMSG
EndFunc
Func _Uncheck($hItem)
    Local $hParent, $hItemCur, $iLevel
    $iLevel = _GUICtrlTreeView_Level($hTree, $hItem)
    $hItemCur = _GUICtrlTreeView_GetFirstChild($hTree, $hItem)
    While $hItemCur And _GUICtrlTreeView_Level($hTree, $hItemCur) > $iLevel
        _GUICtrlTreeView_SetChecked($hTree, $hItemCur, False)
        $hItemCur = _GUICtrlTreeView_GetNext($hTree, $hItemCur)
    WEnd
    $hParent = _GUICtrlTreeView_GetParentHandle($hTree, $hItem)
    If $hParent Then
        While $hParent
            If $hParent <> $hItem Then _GUICtrlTreeView_SetChecked($hTree, $hParent, False)
            $hParent = _GUICtrlTreeView_GetParentHandle($hTree, $hParent)
        WEnd
    EndIf
EndFunc
Func _Check($hItem)
    Local $hParent, $hItemCur, $iLevel
    $iLevel = _GUICtrlTreeView_Level($hTree, $hItem)
    $hItemCur = _GUICtrlTreeView_GetFirstChild($hTree, $hItem)
    While $hItemCur And _GUICtrlTreeView_Level($hTree, $hItemCur) > $iLevel
        _GUICtrlTreeView_SetChecked($hTree, $hItemCur)
        _CallItemFunc($hItemCur)
        $hItemCur = _GUICtrlTreeView_GetNext($hTree, $hItemCur)
    WEnd
    $hParent = _GUICtrlTreeView_GetParentHandle($hTree, $hItem)
    While $hParent
        $hItemCur = _GUICtrlTreeView_GetFirstChild($hTree, $hParent)
        While $hItemCur
            If Not _GUICtrlTreeView_GetChecked($hTree, $hItemCur) And $hItemCur <> $hItem Then ExitLoop 2
            $hItemCur = _GUICtrlTreeView_GetNextSibling($hTree, $hItemCur)
        WEnd
        _GUICtrlTreeView_SetChecked($hTree, $hParent)
        _CallItemFunc($hParent)
        $hParent = _GUICtrlTreeView_GetParentHandle($hTree, $hParent)
    WEnd
EndFunc
Func _WinAPI_GetMessagePos()
    Local $aResult = DllCall("user32.dll", "uint", "GetMessagePos")
    If @error Then Return SetError(@error, @extended, 0)
    Return $aResult[0]
EndFunc
Func _CallItemFunc($hItem)
    For $i = 1 To $hItems[0][0]
        If $hItem = $hItems[$i][0] Then
            Call($hItems[$i][1])
            ExitLoop
        EndIf
    Next
EndFunc

Try to check/uncheck some of the items and click the button. Remember to delete the "Checked items" window before a new button click.

LarsJ

Share this post


Link to post
Share on other sites

#3 ·  Posted (edited)

LarsJ,

Thank you for the response. I do get an error when running the updated code; See below. However, If I continue any way it returns exactly what I was looking for, Perfect thanks.

I:\Autoit\forum.au3(41,54) : ERROR: _ArrayDisplay() called with expression on Const ByRef-param(s)

_ArrayDisplay( GetChecked(), &quot;Checked items&quot; )

C:\Program Files (x86)\AutoIt3\Include\Array.au3(322,163) : REF: definition of _ArrayDisplay().

Func _ArrayDisplay(Const ByRef $avArray, $sTitle = &quot;Array: ListView Display&quot;, $iItemLimit = -1, $iTranspose = 0, $sSeparator = &quot;&quot;, $sReplace = &quot;|&quot;, $sHeader = &quot;&quot;)

fcgnewbie

Edited by fcgnewbie

Share this post


Link to post
Share on other sites

I am using Notepad++ and not Scite so I'm not always seeing all these errors and warnings.

Just replace the line

_ArrayDisplay( GetChecked(), "Checked items" )

with these 2 lines

Local $aArray = GetChecked()

_ArrayDisplay( $aArray, "Checked items" )

and you will not get any errors.

Share this post


Link to post
Share on other sites

LarsJ,

Thanks again for the quick reply. It works without any errors now.

I saw your post AutoItObject example: Enumerating and Browsing the Desktop

and its an awesome piece of code. I have been looking for ability to have a treeview in a listview, so thanks for that. Now I need to piece it all together and to get what I ultimately want to end up with, Something like this.

Posted Image

Many thanks again.

fcgnewbie

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!


Register a new account

Sign in

Already have an account? Sign in here.


Sign In Now
Sign in to follow this  
Followers 0