web development India freelance website designer
This code the first installment in the TreeView Common Control API series, tackles some of the easier treeview messages -
those providing 'special effects' without resorting to owner-drawn controls.
The treeview is a special beast ... compared to the listview, in my opinion, a lot more complicated to manipulate via API.
Instead of referring to items as simple indices based on order, each treeview item has an item handle, and it is this that is
used when manipulating treeview items (see the code for the 'Bold Selected' option). And, like the listview, some changes
to items in the control via API are not reflected in VB's internal collection of treeview items, making maintaining the control's
API-affected contents and VB's internal-collection contents of the control cumbersome.

So we start with the easy ones; ones that don't affect the collection.

Windows' common control header contains the definitions of the calls to manipulate aspects of the treeview control. For
applying changes to the colours used in the control, the header file defines the methods as :

#define TreeView_SetBkColor(hwnd, clr) \
(COLORREF)SNDMSG((hwnd), TVM_SETBKCOLOR, 0, (LPARAM)clr)

#define TreeView_SetTextColor(hwnd, clr) \
(COLORREF)SNDMSG((hwnd), TVM_SETTEXTCOLOR, 0, (LPARAM)clr)

#define TreeView_GetBkColor(hwnd) \
(COLORREF)SNDMSG((hwnd), TVM_GETBKCOLOR, 0, 0)

#define TreeView_GetTextColor(hwnd) \
(COLORREF)SNDMSG((hwnd), TVM_GETTEXTCOLOR, 0, 0)

When using methods that need to deal with the control on a per-item basis (as in the Bold method), the header defines a
message to return the control item identifier (hTreeItem) relative to a 'passed relationship' (in wParam):

#define TreeView_GetNextItem(hwnd, hitem, code) \
(HTREEITEM)SNDMSG((hwnd), TVM_GETNEXTITEM, (WPARAM)code, (LPARAM)(HTREEITEM)(hitem))

These 'relation identifiers' passed in wParam can be one of TVGN_ROOT, TVGN_NEXT, TVGN_PREVIOUS, TVGN_PARENT, TVGN_CHILD, TVGN_FIRSTVISIBLE, TVGN_NEXTVISIBLE, TVGN_PREVIOUSVISIBLE, TVGN_DROPHILITE, and TVGN_CARET.

Finally, note that there is no message is identified providing a means to change the colour of the treeview connecting lines
or +- signs; these are based on the system setting for 3D objects. This limits the setting of fore/back colours to ones that
not only are visually appealing, but provide enough contrast to clearly identify the tree lines.


BAS Module Code

Place the following code into the general declarations area of a bas module:

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

Option Explicit

Public Const GWL_STYLE As Long = (-16)
Public Const COLOR_WINDOW As Long = 5
Public Const COLOR_WINDOWTEXT As Long = 8

Public Const TVI_ROOT As Long = &HFFFF0000
Public Const TVI_FIRST As Long = &HFFFF0001
Public Const TVI_LAST As Long = &HFFFF0002
Public Const TVI_SORT As Long = &HFFFF0003

Public Const TVIF_STATE As Long = &H8

'treeview styles
Public Const TVS_HASLINES As Long = 2
Public Const TVS_FULLROWSELECT As Long = &H1000

'treeview style item states
Public Const TVIS_BOLD As Long = &H10

Public Const TV_FIRST As Long = &H1100
Public Const TVM_GETNEXTITEM As Long = (TV_FIRST + 10)
Public Const TVM_GETITEM As Long = (TV_FIRST + 12)
Public Const TVM_SETITEM As Long = (TV_FIRST + 13)
Public Const TVM_SETBKCOLOR As Long = (TV_FIRST + 29)
Public Const TVM_SETTEXTCOLOR As Long = (TV_FIRST + 30)
Public Const TVM_GETBKCOLOR As Long = (TV_FIRST + 31)
Public Const TVM_GETTEXTCOLOR As Long = (TV_FIRST + 32)

Public Const TVGN_ROOT As Long = &H0
Public Const TVGN_NEXT As Long = &H1
Public Const TVGN_PREVIOUS As Long = &H2
Public Const TVGN_PARENT As Long = &H3
Public Const TVGN_CHILD As Long = &H4
Public Const TVGN_FIRSTVISIBLE As Long = &H5
Public Const TVGN_NEXTVISIBLE As Long = &H6
Public Const TVGN_PREVIOUSVISIBLE As Long = &H7
Public Const TVGN_DROPHILITE As Long = &H8
Public Const TVGN_CARET As Long = &H9

Public Type TV_ITEM
mask As Long
hItem As Long
state As Long
stateMask As Long
pszText As String
cchTextMax As Long
iImage As Long
iSelectedImage As Long
cChildren As Long
lParam As Long
End Type

Public Declare Function SendMessage Lib "user32" _
Alias "SendMessageA" _
(ByVal hwnd As Long, _
ByVal wMsg As Long, _
ByVal wParam As Long, _
lParam As Any) As Long

Public Declare Function GetWindowLong Lib "user32" _
Alias "GetWindowLongA" _
(ByVal hwnd As Long, _
ByVal nIndex As Long) As Long

Public Declare Function SetWindowLong Lib "user32" _
Alias "SetWindowLongA" _
(ByVal hwnd As Long, _
ByVal nIndex As Long, _
ByVal dwNewLong As Long) As Long

Public Declare Function GetSysColor Lib "user32" _
(ByVal nIndex As Long) As Long
'--end block--'


Form Code

Add a treeview (TV1), the common dialog control (CommonDialog1), and five command buttons to a form (Command1,
Command2, Command3, Command4 and Command5). Add the following code:

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

Option Explicit

Private Sub Form_Load()

Dim nodX As Node

'add some test items
Set nodX = TV1.Nodes.Add(, , "R", "Root")
Set nodX = TV1.Nodes.Add("R", tvwChild, "C1", "Child 1")
Set nodX = TV1.Nodes.Add("R", tvwChild, "C2", "Child 2")
Set nodX = TV1.Nodes.Add("R", tvwChild, "C3", "Child 3")
Set nodX = TV1.Nodes.Add("R", tvwChild, "C4", "Child 4")
nodX.EnsureVisible

Set nodX = TV1.Nodes.Add("C3", tvwChild, "C31", "Child 3 SubC 1")
Set nodX = TV1.Nodes.Add("C3", tvwChild, "C32", "Child 3 SubC 2")
nodX.EnsureVisible

Set nodX = TV1.Nodes.Add("C31", tvwChild, "C321", "Child 3 SubC 1 SubC 1")

Set nodX = TV1.Nodes.Add("C4", tvwChild, "C41", "Child 4 Subchild 1")
nodX.EnsureVisible

Command1.Caption = "Set Background"
Command2.Caption = "Set Foreground"
Command3.Caption = "Bold Selected"
Command4.Caption = "Full Row Select"
Command5.Caption = "End"

End Sub


Private Sub Command5_Click()

Unload Me

End Sub


Private Function GetTVBackColour() As Long

Dim clrref As Long
Dim hwndTV As Long

hwndTV = TV1.hwnd

'try for the treeview backcolor
clrref = SendMessage(hwndTV, TVM_GETBKCOLOR, 0, ByVal 0)

'if clrref = -1, then the color is a system color.
'In theory, system colors need to be Or'd with &HFFFFFF
'to retrieve the actual RGB value, but not Or'ing
'seems to work for me. The default system colour for
'a treeview background is COLOR_WINDOW.
If clrref = -1 Then
clrref = GetSysColor(COLOR_WINDOW) ' Or &HFFFFFF
End If

'one way or another, pass it back
GetTVBackColour = clrref

End Function


Private Function GetTVForeColour() As Long

Dim clrref As Long
Dim hwndTV As Long

hwndTV = TV1.hwnd

'try for the treeview text colour
clrref = SendMessage(hwndTV, TVM_GETTEXTCOLOR, 0, ByVal 0)

'if clrref = -1, then the color is a system color.
'In theory, system colors need to be Or'd with &HFFFFFF
'to retrieve the actual RGB value, but not Or'ing
'seems to work for me. The default system colour for
'treeview text is COLOR_WINDOWTEXT.
If clrref = -1 Then
clrref = GetSysColor(COLOR_WINDOWTEXT) ' Or &HFFFFFF
End If

'one way or another, pass it back
GetTVForeColour = clrref

End Function


Private Sub SetTVBackColour(clrref As Long)

Dim hwndTV As Long
Dim style As Long

hwndTV = TV1.hwnd

'Change the background
Call SendMessage(hwndTV, TVM_SETBKCOLOR, 0, ByVal clrref)

'reset the treeview style so the
'tree lines appear properly
style = GetWindowLong(TV1.hwnd, GWL_STYLE)

'if the treeview has lines, temporarily
'remove them so the back repaints to the
'selected colour, then restore
If style And TVS_HASLINES Then
Call SetWindowLong(hwndTV, GWL_STYLE, style Xor TVS_HASLINES)
Call SetWindowLong(hwndTV, GWL_STYLE, style)
End If

End Sub


Private Sub SetTVForeColour(clrref As Long)

Dim hwndTV As Long
Dim style As Long

hwndTV = TV1.hwnd

'Change the background
Call SendMessage(hwndTV, TVM_SETTEXTCOLOR, 0, ByVal clrref)

'reset the treeview style so the
'tree lines appear properly
style = GetWindowLong(TV1.hwnd, GWL_STYLE)

'if the treeview has lines, temporarily
'remove them so the back repaints to the
'selected colour, then restore
If style And TVS_HASLINES Then
Call SetWindowLong(hwndTV, GWL_STYLE, style Xor TVS_HASLINES)
Call SetWindowLong(hwndTV, GWL_STYLE, style)
End If

End Sub


Private Sub Command1_Click()

Dim newclr As Long

With CommonDialog1
.Flags = cdlCCRGBInit 'using RGB colours
.Color = GetTVBackColour() 'pre-select the current colour
.ShowColor 'get the user's choice
newclr = .Color 'and assign to a var
End With

SetTVBackColour newclr 'set the backcolour

End Sub


Private Sub Command3_Click()

Dim TVI As TV_ITEM
Dim hitemTV As Long
Dim hwndTV As Long

'get the handle to the treeview item.
'If the item is selected, use TVGN_CARET.
'To highlight the first item in the root, use TVGN_ROOT
'To hilight the first visible, use TVGN_FIRSTVISIBLE
'To hilight the selected item, use TVGN_CARET
hwndTV = TV1.hwnd
hitemTV = SendMessage(hwndTV, TVM_GETNEXTITEM, TVGN_CARET, ByVal 0&)

'if a valid handle get and set the
'item's state attributes
If hitemTV > 0 Then

With TVI
.hItem = hitemTV
.mask = TVIF_STATE
.stateMask = TVIS_BOLD
Call SendMessage(hwndTV, TVM_GETITEM, 0&, TVI)

'flip the bold mask state
.state = TVIS_BOLD
End With

Call SendMessage(hwndTV, TVM_SETITEM, 0&, TVI)

End If

End Sub


Private Sub Command4_Click()

Dim hwndTV As Long
Dim style As Long

'get the window style
style = GetWindowLong(TV1.hwnd, GWL_STYLE)

'toggle the fullrow select
If style And TVS_FULLROWSELECT Then
style = style Xor TVS_FULLROWSELECT
Else: style = style Or TVS_FULLROWSELECT
End If

'and set it
Call SetWindowLong(TV1.hwnd, GWL_STYLE, style)

End Sub


Private Sub Command2_Click()

Dim newclr As Long

With CommonDialog1
.Flags = cdlCCRGBInit 'using RGB colours
.Color = GetTVForeColour() 'pre-select the current colour
.ShowColor 'get the user's choice
newclr = .Color 'and assign to a var
End With

SetTVForeColour newclr 'set the text colour

End Sub
'--end block--'


Comments
Run the project. Selecting either of the colour options will bring up the common dialog. Select a colour - either from the
available colours or a custom colour. The appropriate part of the treeview will take the selected colour.
If you've installed IE4 (or the newer Java preview), you also have the comctl version required to bold selected items or
select using Full Row Select.

At this time, there appears to be no means to italicize individual treeview items, change the font of individual items, set
individual item colours, or add images as treeview backgrounds without resorting to subclassing and owner-drawing the
control.

In addition, an apparent bug with this control and the full row select will highlight past the left side of a child if that child is
the last item in the treeview, as in the illustration above.

Applying Special Effects to a TreeView

1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 1590 1591 1592 1593

Freelance ASP PHP web development | Web developer India Web development India| Prayagasoft - web designer India, Ecommerce developer india, Ecommerce design