Help using TREEVIEW and IMAGELIST

LBaliao

Member
Hello.

I am using the TREEVIEW and IMAGELIST for the first time. I've successfully populated the TREEVIEW and added images to the IMAGELIST using "custom" in its property sheet. I am having trouble with the following:

1. Expand a node as soon as it is added to the tree.
2. Be able to allow user to click a command button to expand/collapse all the nodes in the tree.
3. On TREEVIEW.Expand, change the image from a closed folder to an open folder and vice-versa.
4. Add an image to the IMAGELIST in the program and not using the property sheet.

I will appreciate your help.

Liza
 

gcampbell

Member
It would be helpful to know which Treeview you are using as there are many variants. Some TreeViews have an Expand and/or Close event that you should be able to trap .. plus some allow you to specify which image to use (from an imagelist) when the folder is open/closed.

Regarding, the ImageList ... it typically isn't possible to add images to the list dynamically. You typically build a list of images for your app then utilize the imagelist where ever required.

If you want to allow maintenance of your ImageList then you'll need to build an interface to maintain your imagelist ... and you'll need to rewrite the WRX file that gets generated (since that is where the actual image is stored).

Later,
Gordon
 

LBaliao

Member
Hi Gordon,

I'm using Microsoft Treeview Control, version 6.0 and Microsoft ImageList Control, version 6.0.

If possible, can you show me an example code to do the functions listed in my original message?

Thanks,
Liza
 

LBaliao

Member
v9stuff.com's got a lot of examples. Unfortunately, after looking at walvisdb viewer, I didn't find the sample codes I am looking for. I have my tree already populated. I just need to know more about "ExpandOnAdd", "ExpandAll" and adding an image to the IMAGELIST programmatically.

TIA
 
I recently had to write some stuff for the Treeview, and found the best approach is to search for vb5/6 examples on the net, and translate them to Progress.

It's important you specify vb6 or vb5 in your google string, as otherwise you might get a load of .net stuff back which is harder to translate.

Here's an example:

http://www.oreilly.com/catalog/vbcnut/chapter/ch05-tv.html


In the first code example,

If nodItem = nodItem.LastSibling Then ...

would become (untested):

IF chNode = chNode:LastSibling THEN ...

Of course you could call nodItem the same name in Progress, I'm just naming variables to my own preferred standards. Really, the only problem you might have is relating the objects in VB (node, tree) to the objects in your Progress frame. After that it's a pretty straightforward translation with a bit of trial and error.

Remember to release your com-handles after you have finished with them!


Lee
 
ps. If you've got a developer's license for the MSTreeView, then presumably you've got the help file (will come with Visual Studio 6).

If not, here's the online help:

http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cmctl198/html/vbobjtreeview.asp

If you find Node properties (Treeview > See Also), you can see to expand a Node, you use the following syntax:

TreeView1.Nodes(1).Expanded = True

In Progress this would become (untested):

chTree:Nodes(1):Expanded = True.

or in my preferred parlance:

chNode:Expanded = True.

To expand all the nodes, you would have to write a recursive
procedure to walk down the node's subtree, and
set Expanded to True on each child.

Lee
 

LBaliao

Member
Thank you for your help. It helped me a lot. I was able to do most of what I planned. So to give back, here's what I've done:

1. To programmatically expand a node in the tree,

ch{CtrlFrameName}:TreeView:Nodes({NodeKey}):Expanded = YES.

2. To programmatically collapse a node in the tree,

ch{CtrlFrameName}:TreeView:Nodes({NodeKey}):Expanded = NO.

3. To change the image on Expand or Collapse of a node,

PROCEDURE {CtrlFrameName}:TreeView:Expand:
DEF INPUT PARAM phNode AS COM-HANDLE NO-UNDO.

/** Change the image to an open folder **/
ch{CtrlFramename}:TreeView:Nodes(phNode:KEY):IMAGE = {ImageKeyName}.

RELEASE OBJECT phNode NO-ERROR.

END PROCEDURE.

PROCEDURE {CtrlFrameName}:TreeView:Collapse:
DEF INPUT PARAM phNode AS COM-HANDLE NO-UNDO.

/** Change the image to an open folder **/
ch{CtrlFramename}:TreeView:Nodes(phNode:KEY):IMAGE = {ImageKeyName}.

RELEASE OBJECT phNode NO-ERROR.

END PROCEDURE.

I still haven't figured out yet how to add images to the IMAGELIST but will keep on trying.

Liza
 

richhcir2

New Member
I recently wrote a progress program including a treeview. I found the best way to do it was to get hold of a copy of VB6, create a COM project, create a form and then drop the ocx onto that form. You can then write all of the treeview stuff in VB and use Public Events and Public Subs to intreract with the Progress side. When you publich the COM project it createsd a new .ocx file that you drop on your Progress form. Under the triggers you'll find all of your Public Events and you can simply call the methods using the treeview:methodName() syntax.

The advantage of this is you don't have to much about with com-handles for the nodes.
Treeview6.0 for example allows for drag and drop but not for drag and drop with scrolling, which makes it useless. In VB you can get around this, using Progress you can't.
 
I needed to use several treeviews communicating with each other so I created a (pseudo - it's not finished yet) SmartObject which I reused once the base component was complete.

Although the component itself uses com handles, the procedures using it to display data don't - they just call and respond to simple methods using node keys, and don't care about what goes on inside.

There was a bit too much 'AbstractionInversion' going on though, and I'm not convinced I did it exactly right, although once the base tree frame was done, the others came quickly.

Your way sounds interesting though (probably much sounder) - have you got a couple of method call examples?
 

richhcir2

New Member
I created a COM project then dropped the treeview control onto it. You then use the new .ocx on your Progress form. You still get all of the original methods and triggers from the treeview.

I then use a temp-table to keep track of each node. As long as you have a unique-key you can write your own addNode,deleteNode,moveNode methods etc..

Here's my moveNode method:


Progress:
crtlframe:treeview:moveNode("node1","node3",4,l-node-key)


VB:
Public Sub moveNode(ByVal sKey As String, ByVal sRelativeKey As String, ByVal iRelationship As Integer, ByVal sNewKey As String)
Dim oNode As Node
Dim oNewNode As Node
Dim oChild As Node
Dim oFirstChild As Node

Set oNode = TreeView1.Nodes(sKey)
Set oNewNode = TreeView1.Nodes.Add(sRelativeKey, iRelationship, sNewKey, oNode.Text, oNode.Image, oNode.SelectedImage)

' move any child nodes in the right order
While oNode.Children > 1
Set oChild = TreeView1.Nodes(oNode.Child.LastSibling.Key)
Set oChild.Parent = oNewNode
Wend
While oNode.Children = 1
Set oChild = TreeView1.Nodes(oNode.Child.Key)
Set oChild.Parent = oNewNode
Wend

TreeView1.Nodes.Remove (sKey)
oNewNode.Selected = True
Set TreeView1.DropHighlight = oNewNode

End Sub


or you can create new triggers such by declaring events :

Public Event nodeSelected()
Public Event rightClickedNode()
Public Event droppedNode(sDropped As String, sDroppedOn As String)

and then raising them in your VB code

Private Sub TreeView1_MouseDown(Button As Integer, Shift As _
Integer, x As Single, y As Single)

TreeView1.DropHighlight = TreeView1.HitTest(x, y)

If Button = vbRightButton Then
RaiseEvent rightClickedNode
End If

End Sub


sorry the code's a bit scruffy, you should be able to see the potential though.
 
Thanks, I'll look more closely at it when I have some time, to see how I can do a similar job to my current one differently next time.
 

pasag001

New Member
Hi!
Here's my code to fill my ImageList at runtime (pcImagePaths contains a comma-separated list of relative paths to bmp's):

FUNCTION lFillImageList returns logical
(pcImagePaths as character) :

define variable oPic as com-handle no-undo.
define variable iCount as integer no-undo.

ghImageList:ListImages:clear().

assign
ghImageList:ImageHeight = 16
ghImageList:ImageWidth = 16
.

do iCount = 1 to num-entries(pcImagePaths):

oPic = load-picture(search(entry(iCount,pcImagePaths))).

ghImageList:ListImages:add(iCount,'Pic':U + string(iCount),oPic).

release object oPic no-error.

end.

return yes.

end function.

That's it. Have fun!

Reagards
pasag001
 
Top