Full Version: Treeview control
UtterAccess Discussion Forums > Microsoft® Access > Interface Design
diegorodriguez
Treeview is a very helpful way to build menus that allow users to quickly discover the new objects set up by programmers on the usual tree structure.

There are some examples on Treeview controls and associated visual basic code to perform several tasks that can be found at some microsoft sites, like this sample at

http://support.microsoft.com/default.aspx?...kb;EN-US;209898

Wish list:
In the attached TREE CONTROL.mdb example, based on above sample, and only containing a table and a form, TreeView is used to show a control panel populated based on a table, and its items can be moved around, changing its dependencies. But now, it would be nice to add an OnClick event so a form should be opened associated to each one of those items. And... even nicer if each item could be represented by an specific icon (a folder, or a packet, or anything...) that could even change if deployed. May anyone have an idea on how to do that?
Marto
Hi,
Check this out web page

HTH
Martin

P.S This is from a thread in UI Design, unfortunately I don't know how to point to that thread
diegorodriguez
Those examples consist of a form its code for Access 9, 2000 and 2003, but they do not seem to run without tables. 'The control has no objects'. The working form looks nice, as you can see following this link from Mr.Sherwood.

http://www.personal.rdg.ac.uk/~shssherd/databases.htm

How can I make them work?
pwrsales
Great job! I wonder do you make use of the MStoolbar control also by any chance?

Best regards

Frank
diegorodriguez
All I need is a sample containing a table and a form with its associated controls to populate a treeview and listview control where I can click on its nodes to open a form.
footbinc
For the ppictures, you could use the imagelist control. Its a parameter when you are adding nodes to the tree.
stevomartin
Hi

I've managed to modify the code in the Microsoft forum with that of another post in these forums (I forget which post it was and apologies to the person who posted it for not crediting them) to make a data driven tree view that automatically launches a form / report etc.

You'll need a table called OBJECTS with the following fields :

object_id int Primary Key
parent_id number
object_name text (for a form preceed with frm_ , for a table tbl_ etc - you'll see this in the code below)
description text This will appear in the tree control

paste the following into the forms module :

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

Private Sub Form_Load()

TreeCtrl.Nodes.Clear

'populate the treeview control
Dim db As Database
Dim rs As Recordset
Dim sName As String
Dim sSQL As String

Set db = CurrentDb()
'open table and find the top level object
sSQL = "SELECT * FROM OBJECTS WHERE parent_id = 0"
Set rs = db.OpenRecordset(sSQL, dbOpenDynaset, dbReadOnly)
With rs
.MoveFirst
Do While .EOF = False
TreeCtrl.Nodes.Add , , rs!object_name, rs!description
'add sub levels
AddChildren rs!object_id, rs!object_name
.MoveNext
Loop
End With

'expand all the nodes
For Each Node In TreeCtrl.Nodes
Node.Expanded = True
Next

Set db = Nothing

End Sub

Sub AddChildren(parent_id As Integer, parent_name As String)

Dim db As Database
Dim rs As Recordset
Dim iParentObject As Integer
Dim sParentName As String
Dim sSQL As String

iParentObject = parent_id
sParentName = parent_name
Set db = CurrentDb

'check no of sub objects
If DCount("object_id", "OBJECTS", "parent_id = " & iParentObject) = 0 Then
'no sub objects
Exit Sub
End If

'get sub levels
sSQL = "SELECT * FROM OBJECTS WHERE parent_id = " & iParentObject
Set rs = db.OpenRecordset(sSQL)
With rs
.MoveFirst
Do While .EOF = False
TreeCtrl.Nodes.Add sParentName, tvwChild, rs!object_name, rs!description
AddChildren rs!object_id, rs!object_name
.MoveNext
Loop
End With

rs.Close

End Sub

Private Sub Form_Open(Cancel As Integer)

DoCmd.MoveSize 0, 0

End Sub

Private Sub TreeCtrl_DblClick()

If Left(TreeCtrl.SelectedItem.Key, 4) = "frm_" Then DoCmd.OpenForm TreeCtrl.SelectedItem.Key
If Left(TreeCtrl.SelectedItem.Key, 4) = "rpt_" Then DoCmd.OpenReport TreeCtrl.SelectedItem.Key, acViewPreview
If Left(TreeCtrl.SelectedItem.Key, 4) = "pdf_" Then Application.FollowHyperlink Mid(TreeCtrl.SelectedItem.Key, 5, Len(TreeCtrl.SelectedItem.Key)), , True
If Left(TreeCtrl.SelectedItem.Key, 4) = "doc_" Then Application.FollowHyperlink Mid(TreeCtrl.SelectedItem.Key, 5, Len(TreeCtrl.SelectedItem.Key)), , True
If Left(TreeCtrl.SelectedItem.Key, 4) = "xls_" Then Application.FollowHyperlink Mid(TreeCtrl.SelectedItem.Key, 5, Len(TreeCtrl.SelectedItem.Key)), , True
End Sub

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

I'm sure the code can be optimised but it seems to work OK

Just out of interest : I've been trying to add a key to refer to the image list but when I add an image key at the end of the nodes.add line I get an invalid key. Anybody any ideas?

Kind regards

Steve
diegorodriguez
Thank you so much for this adaptation. Yes, it comes from the work by Richard Sherwood at

http://www.personal.rdg.ac.uk/~shssherd/databases.htm

Unfortunately (again), it just seems to fail because of unknown reasons. Attached is a small Access 97 treeview.mdb file containing the table objects you suggested and the form including the control tree. May anyone check what was wrong there?

Best regards,

Diego
rsewell
Is there anyway to use develop applications that use Treeview without MS Office Developer?
stevomartin
Hi Diego

I'm not sure why the code doesn't work, however, I've made some small changes to get it working (commented out some lines and changed a constant for a number)

Hopefully this should now work for you

Thanks

Steve

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

Private Sub Form_Load()

TreeCtrl.Nodes.Clear

'populate the treeview control
Dim db As Database
Dim rs As Recordset
Dim sName As String
Dim sSQL As String

Set db = CurrentDb()
'open table and find the top level object
sSQL = "SELECT * FROM OBJECTS WHERE parent_id is null"
Set rs = db.OpenRecordset(sSQL, dbOpenDynaset, dbReadOnly)
With rs
.MoveFirst
Do While .EOF = False
TreeCtrl.Nodes.Add , , rs!object_name, rs!Description
'add sub levels
AddChildren rs!object_id, rs!object_name
.MoveNext
Loop
End With

'expand all the nodes
'For Each Node In TreeCtrl.Nodes
'Node.Expanded = True
'Next

Set db = Nothing

End Sub

Sub AddChildren(parent_id As Integer, parent_name As String)

Dim db As Database
Dim rs As Recordset
Dim iParentObject As Integer
Dim sParentName As String
Dim sSQL As String

iParentObject = parent_id
sParentName = parent_name
Set db = CurrentDb

'check no of sub objects
If DCount("object_id", "OBJECTS", "parent_id = " & iParentObject) = 0 Then
'no sub objects
Exit Sub
End If

'get sub levels
sSQL = "SELECT * FROM OBJECTS WHERE parent_id = " & iParentObject
Set rs = db.OpenRecordset(sSQL)
With rs
.MoveFirst
Do While .EOF = False
TreeCtrl.Nodes.Add sParentName, 4, rs!object_name, rs!Description
AddChildren rs!object_id, rs!object_name
.MoveNext
Loop
End With

rs.Close

End Sub
diegorodriguez
Thank you very much for this new version of your code: works just perfecly.

I'm now working on the ImageList control to add nice and meaningful icons. Any design hint for that?

Diego
stevomartin
I couldn't get the images to display - I keep on getting Invalid Key Error when I added the image list key to the end of the statement that adds the node. If you get it to work I'd be very keen to know how you did it.

As for icons : try this website : http://www.vbaccelerator.com/home/Resource..._Library/Icons/

Regards

Steve
diegorodriguez
To add images to your treeview you should do the following:

1 - Add an ImageListCtrl to the same form where the Treeview control is.
2 - Make sure treeview ImageList property is pointing to the same ImageListCtrl name you just set up before on step 1.
3 - On ImageList, browse and add images. You do not need to care on Keys or Tags. Every image is generating a unique index number (1, 2, 3...) you may refer to later on your addNode line.

You may download the atached treeview.mdb for a sample of what has been done so far, including Steve's code.

Now, I know changing background color for an ActiveX control is hard. But, does anyone know an easy way to do it?

Regards,

Diego
JayNoelOlimpo
hi. i'm new at this tree view control could you help me bout treeview and edit the records in the tree view.
JayNoelOlimpo
cool thanks for the attachment.
ghubbell
Have you had any luck with this? I certainly have not...

Gord
diegorodriguez
Hello again Steve!

Your TreeCtrl code has been working pretty nice, and looks like only one small refinement away from PERFECT.

When I open the form, the tree opens itself to show the 1st branch developed ALWAYS. And I don't want that. I would just want the parents, no children visible until any of the parents are clicked.

Could anyone take a look at the code?


Edited by: diegorodriguez on Wed Dec 29 14:33:33 EST 2004.

Edited by: diegorodriguez on Wed Dec 29 14:34:43 EST 2004.
richm59
Hi,

(
First of all, add a reference to MSComCTL.OCX (in the System32 directory)
Then add the following code for referencing the treeview

Dim TV As MSComctlLib.treeview
Set TV = TreeCtrl.Object
TV.Nodes.Clear 'used like this - you get intellisense!!!
)

Second, you have SingleSel set to true; set it to false, and your worries are over
TV.SingleSel=False; or set it in the property sheet

Or, if you like SingleSel, you can just close the tree in code:
TV.Nodes(1).Expanded = False

HTH,

Rich
diegorodriguez
Okay, now looks just perfect! Many thans, Rich
richm59
QUOTE
Now, I know changing background color for an ActiveX control is hard. But, does anyone know an easy way to do it?

Have you had any luck with this? I certainly have not...


I have been able to do this for controls that are not built into Access. Access controls are not normal - they often do not exist as true windows, so they can't be subclassed, and can't usually receive Windows messages.

If there are any requests, I will try to put together a demo showing how to change the back color of a treeview. But it will take me some time. It's fairly involved, using a number of API calls, and working around some strange painting and refreshing behavior in the treeview control. But it does work well. BTW, you can change many parts of a treeview, if you are willing to spend the time with low-kevel Windows messages. You can change the checkboxes, overlay pictures, manipulate tooltips, etc, etc.

There are a number of web sites out there that show you how to do all of these things (especially MSDN) - but they often require significant code tweaks to get them to work properly in Access.

Rich
diegorodriguez
In the example above, everything works properly, but the displayed order of parent folders and children objects doesn't seem to follow any simple rule (alphabetical, order of appearance in the object table, etc...).

Is there anything in the associated code or control properties controlling this display order?
richm59
The treeview nodes occur in the order that they were added.
During the addition of nodes, you can specify where the new node is added by using the treeview enumerated constants (TreeRelationshipConstants) like:

tvwChild
tvwFirst
tvwLast
tvwNext
tvwPrevious

These constants are used in relation to another "Relative" node:

Tvw1.Nodes.Add "RelativeNodeKey", tvwChild, "KeyText","LabelText"

All of this is detailed in the Treeview help file, and in the online docs at MSDN.com:
http://msdn.microsoft.com/library/default....objtreeview.asp

HTH
Rich
louzam2115
Neat, I like it, I wish I could use it in my database but I have no use for a tree control, maybe I will think of one.
mmsayed
Gord,

You can change the background color of the treeveiw. I found the following code on
http://www.msfn.org/board/index.php?showto...4&st=0&
*******************************************************
Option Explicit 'Needed to make sure declared strings etc work
Private Declare Function SendMessage Lib "User32" Alias "SendMessageA" (ByVal hWnd As Long, ByVal wMsg As Long, ByVal wParam As Long, lParam As Long) As Long 'Used to set the following tweak
Private Declare Function GetWindowLong Lib "User32" Alias "GetWindowLongA" (ByVal hWnd As Long, ByVal nIndex As Long) As Long 'Get treeview handle
Private Declare Function SetWindowLong Lib "User32" Alias "SetWindowLongA" (ByVal hWnd As Long, ByVal nIndex As Long, ByVal dwNewLong As Long) As Long 'Set handle
Private Const GWL_STYLE = -16& 'The current style of treeview
Private Const TVM_SETBKCOLOR = 4381& 'Set Bground Color
Private Const TVM_GETBKCOLOR = 4383& "Get Bground Color
Private Const TVS_HASLINES = 2& 'Misc stuff needed
Dim frmlastForm As Form 'The form using

Private Sub Form_Load()
Dim nodX As Node 'Creates nodX as the default Node
Set nodX = TreeView1.Nodes.Add(, , "R", "Default Plugins") 'Cut all this out of a prog i doing currently tongue.gif
Set nodX = TreeView1.Nodes.Add("R", tvwChild, "DP1", "Bios")
Set nodX = TreeView1.Nodes.Add("R", tvwChild, "DP2", "Video")
Set nodX = TreeView1.Nodes.Add("R", tvwChild, "DP3", "Sound")
Set nodX = TreeView1.Nodes.Add("R", tvwChild, "DP4", "CD/DVD")
Set nodX = TreeView1.Nodes.Add("R", tvwChild, "DP5", "Controllers")
nodX.EnsureVisible ' Make sure it visible
TreeView1.Style = tvwTreelinesText ' Style 4.
TreeView1.BorderStyle = vbFixedSingle
ChangeTreeviewColor 'This will be eventually the event to change the color frown.gif
End Sub


Private Sub ChangeTreeviewColor()
Dim lngStyle As Long 'Explained further on
Call SendMessage(TreeView1.hWnd, TVM_SETBKCOLOR, 0, ByVal RGB(216, 228, 248)) 'Sends a message setting the color defined in the RGB(x,x,x) color value
lngStyle = GetWindowLong(TreeView1.hWnd, GWL_STYLE) 'lngStyle will have the init handle of treeview control
Call SetWindowLong(TreeView1.hWnd, GWL_STYLE, lngStyle - TVS_HASLINES) 'Sets handle
Call SetWindowLong(TreeView1.hWnd, GWL_STYLE, lngStyle) 'Sets handle
End Sub
*****************************************************************

I tweaked the code a bit and was able to replicate the same thing with alot less code. Here is my version:

Private Declare Function SendMessage Lib "User32" Alias "SendMessageA" (ByVal hWnd As Long, ByVal wMsg As Long, ByVal wParam As Long, lParam As Long) As Long 'Used to set the following tweak
Private Const TVM_SETBKCOLOR = 4381& 'Set Bground Color
Private Const TVM_GETBKCOLOR = 4383& 'Get Bground Color

'Call this function in form load event
Private Sub ChangeTreeviewColor()
Call SendMessage(tvwMIS.hWnd, TVM_SETBKCOLOR, 0, ByVal (16764057))
End Sub

HTH,
Mehdi frown.gif
richm59
QUOTE
Private Declare Function SendMessage Lib "User32" Alias "SendMessageA" (ByVal hWnd As Long, ByVal wMsg As Long, ByVal wParam As Long, lParam As Long) As Long 'Used to set the following tweak
Private Const TVM_SETBKCOLOR = 4381& 'Set Bground Color
Private Const TVM_GETBKCOLOR = 4383& 'Get Bground Color

'Call this function in form load event
Private Sub ChangeTreeviewColor()
Call SendMessage(tvwMIS.hWnd, TVM_SETBKCOLOR, 0, ByVal (16764057))
End Sub


I have been used this technique as well, but it my hands, I also have to change the BackColor of each node to match the Treeview background. Not a problem really, but it helps to know about it.

Rich
mmsayed
I'm sorry you are correct. I was going to mention it but forgot.

**To change the backcolor of an image you will have to do this:**
Right click the ImageListCtrl >> ImageListCtrl Object >> Properties >> select "Color" tab>> change the color to match your background color.

**As Rich stated to change the backcolor of a node you will have to do something like this :**
node.backcolor=1234564584

Thanks and HTH frown.gif
Mehdi

Edited by: mmsayed on Wed Jan 12 13:38:24 EST 2005.
richm59
Hi Mehdi,

Thanks for the tip about the Image Control Background color. It fixes an old problem for me!

Rich

Edited by: richm59 on Thu Jan 13 14:52:29 EST 2005.
mmsayed
Not a problem, glad to help (with atleast one issue)!

Mehdi frown.gif
mmsayed
Just a side note to color the Node you need to declare it as an object and then do the backcolor thing:

Dim objCurrNode as Object

objCurrNode.backcolor=16764057

I usually just add this line in my loop as I am building the tree.

HTH,
Mehdi
linhqhta
thanks for posted!
williams9969
I really like this treeview but am limited to only three icons.

I would like to be able to apply many different icons...any ideas?

Thanks!!!!!!!!
williams9969
Noone has a working example of a treeview with different ICONS on it? I truely
want to use this as a menu for my upcoming DB...please help.

thanks!!!!!!!!!!!!!!!!
Clippit
I don't have a working example handy with several icons but have done this in the past. It's just a matter of adding more images to your ImageList control and then in the code that fills the treeview determining which icons applies to each node. If you have three now it should be easy to add more.
williams9969
Thanks for the reply.

I assumed it would be too...but cannot figure it out. I have tried
for awhile now...applying different options to the code(s) above....but no luck

Any ideas on what to do to it?

Thanks again for the help!
Clippit
Have you added a new image to the imagelist?

What's your code for adding nodes to the treeview?
williams9969
Here is the code I am using...same as above...

CODE
  

Option Compare Database

Option Explicit



Private Sub Form_Load()

Dim TV As MSComctlLib.treeview

Dim db As Database

Dim rs As Recordset

Dim sName As String

Dim sSQL As String

Dim Cap As String



TreeCtrl.Nodes.Clear



'populate the treeview control



Set TV = TreeCtrl.Object



TV.Nodes.Clear 'used like this - you get intellisense!!!



TV.SingleSel = False



Set db = CurrentDb()

'open table and find the top level object

sSQL = "SELECT * FROM OBJECTS WHERE parent_id is null"

Set rs = db.OpenRecordset(sSQL, dbOpenDynaset, dbReadOnly)

With rs

.MoveFirst

Do While .EOF = False

TreeCtrl.Nodes.Add , , rs!object_name, rs!Description, 1, 2

'add sub levels

AddChildren rs!object_id, rs!object_name

.MoveNext

Loop

End With



'Call this function in form load event

'expand all the nodes

'For Each Node In TreeCtrl.Nodes

'Node.Expanded = True

'Next



Set db = Nothing



End Sub



Sub AddChildren(parent_id As Integer, parent_name As String)



Dim db As Database

Dim rs As Recordset

Dim iParentObject As Integer

Dim sParentName As String

Dim sSQL As String



iParentObject = parent_id

sParentName = parent_name

Set db = CurrentDb



'check no of sub objects

If DCount("object_id", "OBJECTS", "parent_id = " & iParentObject) = 0 Then

'no sub objects

Exit Sub

End If



'get sub levels

sSQL = "SELECT * FROM OBJECTS WHERE parent_id = " & iParentObject

Set rs = db.OpenRecordset(sSQL)

With rs

.MoveFirst

Do While .EOF = False

'******************************************************************************

TreeCtrl.Nodes.Add sParentName, 4, rs!object_name, rs!Description, 3

'******************************************************************************

AddChildren rs!object_id, rs!object_name

.MoveNext

Loop

End With



rs.Close



End Sub


The problem I am having is using more then 3 icons...

I want to be able to add an icon specific to what are is on the treeview...not just one icon for the parent inactive,
then one active...then a different icon for the child

I have about 9 sections(plus) that I want to be able to apply different icons to.

Thanks for the interest and the help!!!




Edited by: williams9969 on Sat Sep 13 13:22:49 EDT 2008.
williams9969
Oh...sorry for not answering part of ??

Yes, I have loaded about 10 icons...trying to find a way

Thanks again!
Clippit
You need to figure out how to determine in your code what icon (by index number) applies to your node, and then specify that index number instead of the 3 that you're using now when you add a child. (The last parameter on the Nodes.Add statement.)

What do the other icons mean? How will Access know from your data which icon applies?
williams9969
Steve-

Thanks for the help....I have been trying to figure that part out....

I am a VBA novice and don't know really how to apply this.

I appreciate the help and I will keep pounding away at it.

Thanks again!!!
Clippit
Sounds good.
williams9969
Still no luck...anyone?
Clippit
What's the question?
Clippit
I have a multi-image demo that I've been building for another purpose that is almost finished and I'll post likely tomorrow.
williams9969
You are awesome....thanks so much
Clippit
OK. Take a look at the attached. It's built using the Northwind tables to demonstrate a treeview with images. The method for accessing records is not very efficient- it's meant to be simple so that the focus can be on the treeview code.

There's a databse and 10 .bmp files that have to reside in the same folder as the database.
williams9969
Steve

Exactly what I was looking for.

Thanks so much for your work...looks great

Again, thanks!!!
javadudd
Hi Steve,

I'm trying to create an Access 97 database which manages 3 related tables say Products, Groups and Types.
A combination of these fields then relate to a Directory Structure.

So say:
Products have the fields Product, Number and Group
Groups have the fields Letter and Group
Types have the fields Letter and Type

A directory structure would be created from example c:\temp\Group\Product 1 if it did not already exist.

I thought that this could be applied to the work you have done on the Treeview Control but I'm not quite sure how to begin.

Could you please give me some pointers or suggestions on how I might structure this.

Is there a way to say put in a default path i.e. c:\temp and then have the Treeview control read the underlying Directories and add folders to the required tables?

Thanks for any help you can give.

Drew
Clippit
Treeviews don't read folders. You'd have to write VBA code to look at each folder and add the files as nodes to the treeview. There's a post in the UA archive that loads folders into a treeview here.
javadudd
Thanks Steve

Drew.
This is a "lo-fi" version of our main content. To view the full version with more information, formatting and images, please click here.