Jump to content

Treeview control


Jon
 Share

Recommended Posts

  • Administrators

I'm looking to add some functions like ControlListView() but for treeviews. The problem is I can't work out the best way of doing it - what sort of operations and how should the parameters be specified?

ControlTreeView("title", "text", "control", "command", 1, 2)

Commands:

GetCount - return the number of items. Just for this level? For all levels? Include expanded/contracted items?

GetSelected - what would it return? The text? Or an index?

Indexes - Given that a tree views are hierarchical how can this be expressed? "strlevel1|strlevel2" or "nitem1|nitem2". Both?

The code is not too difficult, but the best parameters to use is hard!

Link to comment
Share on other sites

Just to think about...

Being ideal solution GUI4CLI has the following TREEVIEW command set:

ADD ItemText [CHILD|ROOT]

Will add an item to the end of the list of the same "branch" (ie level) of the treeview as the current item. The argument must be the text of the item you want to add.

Optionally, you can also give one of the following keywords:

CHILD Will cause the new item to be added as a child of the current item. If the current item already has children, it will be added to the bottom of the list.

ROOT Will add the item as a new root item, ie will append it to the 1st level of the treeview.

The newly added item becomes current.

CHECK [ON/OFF/1/0]

Use this to set a checkbox on/off. You can give ON (or "1") or OFF (or "0"). If you don't give anything, it will be set on. To give a treeview checkboxes, give the CHECK style.

CLEAR (no arguments)

Clears the treeview, deleting all items.

COLLAPSE (no arguments)

(or CONTRACT) - Will collapse the children of the current item

DELETE (no arguments)

Will delete the current item and any children it has. The next item after it, if any, will become current.

EMPTY (no arguments)

Will delete only the children of the item, without deleting the item itself.

EXPAND (no arguments)

Will expand the branch of the current item, if it has children.

GET TVVariableName NormalVariableName

Will retrieve a treeview variable which has been set with the TV SET command, and put it into a normal variable. You can do the same with the $$TV.GET.name internal variable.

GOTO Keyword

(or GO) - This will go to a given record, and make it current, so you can then access it via internal variables, or insert items after it etc.. You can give the following keywords:

ROOT Goto the top of all items, ie the 1st item in the root level of the treeview

FIRST (or TOP) - Will go to the first item of the same level (branch) as the currently current item.

LAST (or BOTTOM) - Will go to the last item of the same level as the currently current item.

NEXT Will go to the next item.

PREV Goto the previous item

CHILD Goto the first child item of the current item, if any.

PARENT Goto the parent of the current item. If the current item is in the root level, the current item will be set to nothing.

TVNEXT Goto the next item, recursing through all items in the treeview. Using this you can list all the items in a treeview, one after the other, irrespective of their level, as if you had expanded all of the branches and were reading it from top to bottom.

#number A '#' character, followed by an index path will goto the given index path.

INDEX IndexPath

Will select and make current an item. The argument should be the full index path of an item.

INSERT ItemText

Will insert an item after the current item. The argument must be the text of the item you want to add.

The newly added item becomes current.

LOAD Filename

Load a Treeview file. The argument must be the full path of the file. Assigns are allowed.

PATH TextPath

Will select and make current an item. The argument should be the full text path of an item.

PROPERTY [-]Property

Will set a "boolean" (ie true or false) property for the current item. Note that this setting will not be saved if you save the treeview with TV SAVE.

Treeview PROPERTY DRAG // allow item to be dragged

Treeview PROPERTY -DRAG // do not allow it

The following are the properties you can set:

DRAG - Allow item to be dragged. Give "-DRAG" to forbid the current item from being dragged. (set to true by default in treeviews that have the DRAG or ARRANGE styles set).

DROP - Allow the item to be dropped onto. (true by default)

Note that, currently, these setting will not be saved if you save the treeview with TV SAVE.

PUT NewItemText

(or TEXT) - Will change the text of the current item. You must give the new text you want:

Treeview PUT "This is the new text"

SAVE Filepath [Flags]

Save the treeview as a Treeview file. The argument is the full path of the file (assigns allowed). You can optionally give the following flags:

NOVARS - If any of the treeview items has variables (see the SET command below) they will automatically be saved with the treeview. Give this flag to avoid this.

ICON - The icon indexes of the items will not, by default, be saved with the listview. Give this keyword to save them, if you want.

Treeview SAVE "c:/mytv.gtv" ICON

SET TVVariableName String

This command will set a variable for the current treeview item. If the variable exists it will be replaced. If it doesn't, it will be created. Every item in a treeview can have its own list of variables. They are independant, belonging only to that item. You can retrieve the contents of the variable with the $$TV.GET.name internal variable or the TV GET command..

Use TV #this mytv

TV set myvar "some text"

say 'this item myvar = $$tv.get.myvar'

SORT [flag]

Will sort the treeview alphabetically, ascending. Optionally, you can give one of the following keywords.

PARFIRST, which will cause it to put the items having children first, like the directory treeviews do.

BRANCH, to sort only the items in the branch of the current item, and not the whole listview.

TOGGLE (no arguments)

Will toggle the state of the children of the current item, if any - ie if branch is expanded it will contract and vice versa.

But it can be job for years, though.

Thanx.

The point of world view

Link to comment
Share on other sites

This is concept of Dimitris:

Treeviews understand 3 different types of paths:

The TEXT path:

This is a path made up of the texts of each item, from the root of the tree to the given item, separated by "/" characters, like

"Item 2/Subitem 5/SubSubitem 0"

The INDEX path

This is a path made up of the indexes of each item, from the root of the tree to the given item, separated by "/" characters. The index of each item is the position it is at in its level. The top item is item No 0. Example:

"2/5/0"

The DIRECTORY path:

This is for Directory Treeviews and is a filesystem path to a folder, like:

"C:/mydir/my other dir"

--------------------------------------------------------------------------------

For example, in the following treeview:

Item 1

Child 1

Child 2

SubChild1

SubChild2

Item 2

Child 1

Child 2

Item 3

Item 4

Item 5

Child 1

Child 2

SubChild1

SubSub1

SubSub2

SubChild2

SubSub1

To indicate item "SubSub2":

Text path : "Item 5/Child 2/SubChild1/SubSub2"

Index path: "4/1/0/1"

He introduced the own format file .gtv - textual view of tree.

It's very cool. It can include level, icon, item content and other useful infos.

The point of world view

Link to comment
Share on other sites

I'm looking to add some functions like ControlListView() but for treeviews.

The problem is I can't work out the best way of doing it -

what sort of operations and how should the parameters be specified?

ControlTreeView("title", "text", "control", "command", 1, 2)

Commands:

GetCount - return the number of items. Just for this level? For all levels? Include expanded/contracted items?

GetSelected - what would it return? The text? Or an index?

Indexes - Given that a tree views are hierarchical how can this be expressed? "strlevel1|strlevel2" or "nitem1|nitem2". Both?

The code is not too difficult, but the best parameters to use is hard!

The best concept would be work with real item node numbers (handles) as in Auto3Library:

Look at my example:

#include <GUIConstants.au3>
#include <GuiTreeView.au3>
#include "_TreeViewGetItemState.au3"

const $TVGN_ROOT = 0

$gui = GUICreate("Treeview item state",212,212)
$treeview = GUICtrlCreateTreeView (6,6,200,160,BitOr($TVS_HASBUTTONS,$TVS_HASLINES,$TVS_LINESATROOT,$TVS_CHECKBOXES),$WS_EX_CLIENTEDGE)
$h_tree = ControlGetHandle("", "", $treeview)

$root = GUICtrlCreateTreeViewitem ("Root",$treeview)
$item1 = GUICtrlCreateTreeViewitem ("Item 1",$root)
$item2 = GUICtrlCreateTreeViewitem ("Item 2",$root)
$item3 = GUICtrlCreateTreeViewitem ("Item 3",$root)
$item4 = GUICtrlCreateTreeViewitem ("Item 4",$root)
$item5 = GUICtrlCreateTreeViewitem ("Item 5",$root)

GUICtrlSetState($item2,$GUI_CHECKED) 
GUICtrlSetState($item4,$GUI_CHECKED) 
_GUICtrlTreeViewExpand($gui, $treeview, 1, 0)

$show = GUICtrlCreateButton("Show", 70, 180, 70, 20)

GUISetState ()
While 1
    $msg = GUIGetMsg()
    Select
        Case $msg = $show
            Show()
        Case $msg = $GUI_EVENT_CLOSE
            ExitLoop
    EndSelect
WEnd
GUIDelete()
Exit

Func Show()
    $result = ""
        $h_item = GUICtrlSendMsg($treeview, $TVM_GETNEXTITEM, $TVGN_ROOT, 0)
    $result &= GetItemInfo($h_item)
    $h_item = GUICtrlSendMsg($treeview, $TVM_GETNEXTITEM, $TVGN_CHILD, $h_item)
        While 1
        $result &= GetItemInfo($h_item)
        $h_item = GUICtrlSendMsg($treeview, $TVM_GETNEXTITEM, $TVGN_NEXT, $h_item)
        If $h_item <= 0 Then ExitLoop
    WEnd
        MsgBox(64, "Result", $result)
EndFunc

Func GetItemInfo($h_item)
    $text = _TreeViewGetItemText($h_tree, $h_item)
    $state = _TreeViewGetItemState($h_tree, $h_item)
        If BitAND($state, $TVIS_STATEIMAGEMASK) = 0x2000 Then; unchecked=0x1000 checked=0x2000
        $state = "checked"
    Else
        $state = "unchecked"
    EndIf
        Return $text & @TAB & $state & @CRLF
EndFunc

*** with new ControlTreeView:

#include <GUIConstants.au3>
#include <GuiTreeView.au3>

$gui = GUICreate("Treeview item state",212,212)
$treeview = GUICtrlCreateTreeView (6,6,200,160,BitOr($TVS_HASBUTTONS,$TVS_HASLINES,$TVS_LINESATROOT,$TVS_CHECKBOXES),$WS_EX_CLIENTEDGE)
$h_tree = ControlGetHandle("", "", $treeview)

$root = GUICtrlCreateTreeViewitem ("Root",$treeview)
$item1 = GUICtrlCreateTreeViewitem ("Item 1",$root)
$item2 = GUICtrlCreateTreeViewitem ("Item 2",$root)
$item3 = GUICtrlCreateTreeViewitem ("Item 3",$root)
$item4 = GUICtrlCreateTreeViewitem ("Item 4",$root)
$item5 = GUICtrlCreateTreeViewitem ("Item 5",$root)

GUICtrlSetState($item2,$GUI_CHECKED) 
GUICtrlSetState($item4,$GUI_CHECKED) 
$root = ControlTreeView($h_tree, '', 'GetRootItem')
ControlTreeView($h_tree, '', 'Expand', $root, 1)

$show = GUICtrlCreateButton("Show", 70, 180, 70, 20)

GUISetState ()
While 1
    $msg = GUIGetMsg()
    Select
        Case $msg = $show
            Show()
        Case $msg = $GUI_EVENT_CLOSE
            ExitLoop
    EndSelect
WEnd
GUIDelete()
Exit

Func Show()
    $result = ""
      $h_item = ControlTreeView($h_tree, '', 'GetRootItem')
    $result &= GetItemInfo($h_item)
    $h_item = ControlTreeView($h_tree, '', 'GetNextChildItem', $h_item)
        While 1
        $result &= GetItemInfo($h_item)
      $h_item = ControlTreeView($h_tree, '', 'GetNextItem', $h_item)
        If $h_item <= 0 Then ExitLoop
    WEnd
        MsgBox(64, "Result", $result)
EndFunc

Func GetItemInfo($h_item)
    $text = ControlTreeView($h_tree, '', 'GetItemText', $h_item)
    $state = ControlTreeView($h_tree, '', 'GetItemState', $h_item)
        If BitAND($state, $TVIS_STATEIMAGEMASK) = 0x2000 Then; unchecked=0x1000 checked=0x2000
        $state = "checked"
    Else
        $state = "unchecked"
    EndIf
        Return $text & @TAB & $state & @CRLF
EndFunc

***

GetSelected - return handle of item which can be used in GetItemText, see Func _TreeView_GetSelection($hWnd)

GetItemCount - return the number of items, optional parameters: item

if no given item then count all treeview items - as in A3L Func _TreeView_GetCount($hWnd, $hNode=0)

for expaned/contracted options can be maded UDF functions based of few base ControplTreeView functions

So this is the same style as one used in Auto3Library,

look into A3lTreeView.au3 I think this is the best solution.

In ControlTreeView() will be only Title and Text instead of Handle ($hWnd)

look at this nice example from A3lTreeView:

Func _TreeView_FindNodeEx($hWnd, $sPath, $hStart=0, $sDelim="|")
  Local $iIndex, $aParts

  $iIndex = 1
  $aParts = StringSplit($sPath, $sDelim)
  if $hStart = 0 then $hStart = _TreeView_GetFirstNode($hWnd)
  while ($iIndex <= $aParts[0]) and ($hStart <> 0)
    if StringStripWS(_TreeView_GetText($hWnd, $hStart), 3) = StringStripWS($aParts[$iIndex], 3) then
      if $iIndex = $aParts[0] then Return $hStart
      $iIndex += 1
      _TreeView_Expand($hWnd, $hStart)
      $hStart = _TreeView_GetFirstChild ($hWnd, $hStart)
    else
      $hStart = _TreeView_GetNextSibling($hWnd, $hStart)
    endif
  wend
EndFunc

EDIT: Idea from Valery san be used with some wrapper UDFs, it's less general then Auto3Library style with real node handles

Edited by Zedna
Link to comment
Share on other sites

  • Administrators

Think that's way too complicated if you just want to say "please expand the C:\Dir1\Dir2 treeview"... The underlying item numbers can change at any time when it's not in a program you control too.

Link to comment
Share on other sites

Think that's way too complicated if you just want to say "please expand the C:\Dir1\Dir2 treeview"... The underlying item numbers can change at any time when it's not in a program you control too.

There is no problem to make FindItem and FindItemEx commands (like in Auto3Library) - see PaulIA's sources: FindItemEx does exactly what you expect Jon "C:\Dir1\Dir2 treeview"

These functions return handle of finded node and then you can use every other function on this node (Expand/Collapse/Select/Check/UnCheck/...)

PaulIA's concept is really the BEST one!

And if you need some more sofisticated functions, you can make them as wrappers over base concept functions (as Auto3Library does for example look at: _TreeView_Level($hWnd, $hNode))

EDIT: I'm using Au3Library's TreeView functions heavily in many of my work projects, so I exactly know what I'm talking about

Edited by Zedna
Link to comment
Share on other sites

Think that's way too complicated if you just want to say "please expand the C:\Dir1\Dir2 treeview"... The underlying item numbers can change at any time when it's not in a program you control too.

In many situations I need to go through whole TreeView and with Auto3Library concept this is very simple:

$hNext = _TreeView_GetFirstNode($hTree)
while $hNext <> 0
    _Lib_ConsoleWrite("Node Level .............: " & _TreeView_Level           ($hTree, $hNext))
    _Lib_ConsoleWrite("Node Text ..............: " & _TreeView_GetText       ($hTree, $hNext))
    _Lib_ConsoleWrite()
    $hNext = _TreeView_GetNext($hTree, $hNext)
wend

Look at

C:\Program Files\AutoIt3\Auto3Lib\treeview 1.au3

C:\Program Files\AutoIt3\Auto3Lib\treeview 2.au3

Edited by Zedna
Link to comment
Share on other sites

  • Administrators

I'm not talking about AutoIt GUI control here - this is purely for automating other applications and needs to be simple. Like 1 line native functions.

I don't want to have to use native handle nodes because that's broken under x64 (without adding a new HTREENODE type to our variant type which isn't going to happen! :) )

Link to comment
Share on other sites

I'm not talking about AutoIt GUI control here - this is purely for automating other applications and needs to be simple. Like 1 line native functions.

I'm using Auto3Library TreeView functions primary for automating other applications.

I don't want to have to use native handle nodes because that's broken under x64 (without adding a new HTREENODE type to our variant type which isn't going to happen! :) )

This is very said. Fortunatelly there still will be Auto3Library in the future which is with its simple/effective concept my favorit number ONE. I doubt you will not make simple ControlTreeView usable for most of my robust treeview automating without item handles  :)

Item handles would have another positive: You can use own SendMessage for functions not implemented in ControlTreeView()

Link to comment
Share on other sites

I don't want to have to use native handle nodes because that's broken under x64 (without adding a new HTREENODE type to our variant type which isn't going to happen! :) )

I don't understand exactly.

Internally you need HTREENODE any way so you must solve x64 problem any way.

In ControlTreeView() hNode can be used only as general handle/number (without need to have whole HTREENODE structure).

Just FindItem returns hNode - it's number

and GetItemText use this hNode - number (no structures here)

Edited by Zedna
Link to comment
Share on other sites

  • Administrators

I don't understand exactly.

Internally you need HTREENODE any way so you must solve x64 problem any way.

Internally within a C function, yes. Exposed via the variant type so you can do things in AutoIt with it, no.

In ControlTreeView() hNode can be used only as general handle/number (without need to have whole HTREENODE structure).

Just FindItem returns hNode - it's number

and GetItemText use this hNode - number (no structures here)

No. You are using an integer. On 32 bit machines integers and pointers (HTREENODE) are the same. On 64bit machines they are not. Any code that assumes you can store pointers in a integer is broken - simple as that :) This is why none of the DllCall and DllStruct code works in the x64 version of AutoIt - because it is all based on the concept that you can mess around with handles and ints.
Link to comment
Share on other sites

Internally within a C function, yes. Exposed via the variant type so you can do things in AutoIt with it, no.

No. You are using an integer. On 32 bit machines integers and pointers (HTREENODE) are the same. On 64bit machines they are not. Any code that assumes you can store pointers in a integer is broken - simple as that :) This is why none of the DllCall and DllStruct code works in the x64 version of AutoIt - because it is all based on the concept that you can mess around with handles and ints.

In that case also whole Auto3Library (and many other UDFs like GuiListView.au3 which works with handles this way) will not work under x64 if I understand your notes, will it?

Edited by Zedna
Link to comment
Share on other sites

  • Administrators

In that case also whole Auto3Library (and many other UDFs like GuiListView.au3 which works with handles this way) will not work under x64 if I understand your notes, will it?

Correct. :)

The only true pointer type that can be used at the moment is a window handle (hWnd). These are stored properly on both the 32 and 64bit versions. I may try and change the window handle type into a generic pointer type which may help many of these problems, but that's a project in itself.

Link to comment
Share on other sites

  • Administrators

In a test version I've got ControlTreeView() working with a couple of functions: Select, GetText

The current item conventions are:

Text searching: "Level|SubLevel|SubSubLevel"

Index: "#0|#2"

Combo searching: "Level|#2"

As they are all strings then I can always retrofit HTREEITEM pointers at some point if I get around to supporting native pointers in variants.

I'll add some more features (Expand,Collapse, ExpandToggle, Click, Count) and then release it for a beta and see if it's any use.

Link to comment
Share on other sites

I'll add some more features (Expand,Collapse, ExpandToggle, Click, Count) and then release it for a beta and see if it's any use.

My advice: Make naming convence for new ControlTreeView commands as much compatible as can be with existing ControlListView commands.

Edited by Zedna
Link to comment
Share on other sites

Create an account or sign in to comment

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

Create an account

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

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

  • Recently Browsing   0 members

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