Click to See Complete Forum and Search --> : Treeview in VB


dza613
June 1st, 1999, 01:58 AM
How can I delete a child from a node and, after saving any relevant info from the child, put it back in the node in the same place. thanx in advance

Be well,

Daniel

Ravi Kiran
June 1st, 1999, 02:39 AM
Hi,

I have seen some code at http://www.mvps.org/ccrp/
which wraps the treeview's access into convienient VB functions. Using these functions, save all the information about the child nodes of the to-be-deleted node along with its parent info too and then delete using Remove property of nodes collection :
tv.Nodes.Remove(to_be_deleted_tv_item.index)

When you want to restore it back, first get the Node item that corresponds to the deleted items parent and create a new node with Add method specifying this parent. Recursively you can restore all of child nodes of the deleted node also. Addition code :
tv.Nodes.Add lpParentNd, tvwChild, , DeletedNdtext

dza613
June 1st, 1999, 06:17 AM
This gave me a good hint, but I don't know what code you are talking about. Could you be more specific?

Thanks

Daniel

Be well,

Daniel

Ravi Kiran
June 2nd, 1999, 01:49 AM
The code that i have with me, says "Brad Martinez" @ mvps . These days there seems to be lot of restrictions on code copy & reuse and i hope i am not violating any...

I am posting the complete code, that i had taken from which-ever site here. The changes done are code formating to suite my style, and i dont think it is such a crime :-)

Ravi.
----

'
'Visual Basic TreeView API Routines
'Posted Friday April 17, 1998
'Updated Tuesday January 19, 1999
'
'Adding Checkboxes to a TreeView via API Related Topics
' VBnet Frames
'Applies to: VB4-32, VB5, VB6 (comctl32.ocx)
'
'
'
' Prerequisites
'
'Enhanced Comctl32 functionality is only available to users with comctl32.dll version 4.70 or greater installed. This dll is typically installed with IE3.x or IE4. See the Dev Centre for information on redistributing the 4.72 version of comctl32.dll.
'Visual Basic 6 users have extended functionality built-in to the newer mscomctl32.ocx, which does not rely on the Windows comctl32.dll. This code is targeted towards users opting for the older comctl32.ocx using comctl32.dll.
'
'
'--------------------------------------------------------------------------------
'
'
'So I says to Brad "Brad," I says, "I'm working on doing a treeview checkbox demo." Ding goes the mailbox ... and here it is, using a checkbox in a treeview, courtesy of Brad Martinez, the Mad Coder.
'Recent newsgroup postings have asked how to mimic the Advanced Options page displayed in Internet Explorer 4. Initially I thought of using the listview with checks and indents, but after someone suggested that the items on the page were collapsible, I investigated the treeview styles. Sure enough, a TVS_CHECKBOXES style was available. So while it was now easy to display the checkboxes (by calling SetWindowLong), I wanted to do a second request ... selecting/deselecting child item checkboxes, and identifying which nodes were checked and unchecked.
'
'API-wise, the treeview, compared to the listview, is a much different beast.
'Where the listview items are consecutively numbered form 0 to Count -1 (via API)
'or 1 to Count (using the VB version), treeviews, because of their hierarchical
'nature, use item identifiers instead of indexes (called hitems).
'Luckily, for most VB users never advancing past the surface of the controls,
'this complex system is hidden, and as far as the treeview goes, this is a
'blessing. But when you have to get under the hood, you soon see that MS
'obviously gave the task of designing the treeview to Morgan the Maniac.
'The innards *are* complex. Hopefully, the code below is presented in a
'relatively well thought-out way in order to guide you through the dark
'corridors of the API treeview.
'
'to keep the code intact while the demo is created, I suggest doing a select
'all/copy for the entire page, then pasting everything into notepad and
'extracting the code from there. This will assure that all line breaks occur
'correctly.
'
'
'
'
' BAS Module Code
'
'The BAS module will contain the base APIs and a subset of generic TreeView
'functions (those prefaced with "Treeview_"). These correspond by name to
'their C-macro counterparts, so over time here you will build up pretty much
'the complete collection. Add the following code to a BAS module:
'
'--------------------------------------------------------------------------------
'
'
option Explicit
'
'Brad Martinez, http://www.mvps.org/ccrp/
'

'These are the indices of the treeview
'checkbox state images when the treeview
'TVS_CHECKBOXES style bit is set.
public Const IIL_UNCHECKED as Long = 1
public Const IIL_CHECKED as Long = 2

public Const GWL_STYLE = (-16)

Declare Function GetWindowLong Lib "user32" _
Alias "GetWindowLongA" _
(byval hwnd as Long, _
byval nIndex as Long) as Long

Declare Function SetWindowLong Lib "user32" _
Alias "SetWindowLongA" _
(byval hwnd as Long, _
byval nIndex as Long, _
byval dwNewLong as Long) as Long

Declare Function SendMessageAny Lib "user32" _
Alias "SendMessageA" _
(byval hwnd as Long, _
byval wMsg as Long, _
byval wParam as Any, _
lParam as Any) as Long

public Type POINTAPI 'pt
X as Long
Y as Long
End Type

Declare Function GetCursorPos Lib "user32" _
(lpPoint as POINTAPI) as Long

Declare Function ScreenToClient Lib "user32" _
(byval hwnd as Long, _
lpPoint as POINTAPI) as Long

Declare Function GetAsyncKeyState Lib "user32" _
(byval vKey as Long) as Integer

'--------------------------------------------
'treeview definitions defined in Commctrl.h at:
'http://premium.microsoft.com/msdn/library/sdkdoc/c67_4c8m.htm

'style
public Const TVS_CHECKBOXES as Long = &H100 '>= IE3

'messages
public Const TV_FIRST as Long = &H1100
public Const TVM_GETITEM as Long = (TV_FIRST + 12)
public Const TVM_SETITEM as Long = (TV_FIRST + 13)
public Const TVM_HITTEST as Long = (TV_FIRST + 17)

public Type TVITEM 'was TV_ITEM
mask as Long
hItem as Long
state as Long
stateMask as Long
pszText as string 'Long 'pointer
cchTextMax as Long
iImage as Long
iSelectedImage as Long
cChildren as Long
lParam as Long
End Type

'TVITEM.mask flags
public Const TVIF_TEXT as Long = &H1
public Const TVIF_STATE as Long = &H8
public Const TVIF_HANDLE as Long = &H10

'TVITEM.state bit value
public Const TVIS_STATEIMAGEMASK as Long = &HF000

public Type TVHITTESTINFO 'was TV_HITTESTINFO
pt as POINTAPI
flags as Long
hItem as Long
End Type

'TVHITTESTINFO.flags value
public Const TVHT_ONITEMSTATEICON as Long = &H40

'User-defined as the maximum treeview item
'text length. If an items text exceeds this
'value when calling GetTVItemText there could
'be problems...
public Const MAX_ITEM = 256
public Const TVM_GETNEXTITEM as Long = (TV_FIRST + 10)

'TVM_GETNEXTITEM wParam values
public Enum TVGN_FLAGS
TVGN_ROOT = &H0
TVGN_NEXT = &H1
TVGN_PREVIOUS = &H2
TVGN_PARENT = &H3
TVGN_CHILD = &H4
TVGN_FIRSTVISIBLE = &H5
TVGN_NEXTVISIBLE = &H6
TVGN_PREVIOUSVISIBLE = &H7
TVGN_DROPHILITE = &H8
TVGN_CARET = &H9
#If (WIN32_IE >= &H400) then
TVGN_LASTVISIBLE = &HA
#End If
End Enum

public Declare Function SendMessageArray Lib _
"user32" Alias "SendMessageA" _
(byval hwnd as Long, byval wMsg as Long, _
byval wParam as Long, lParam as Any) as Long


public Function IsTVItemChecked(hwndTV as Long, _
hItem as Long) as Boolean

'---------------------------------------------------
'Determines if the current state image of the
'specified treeview item is set to the checked
'checkbox image index.
'
'hwndTV - treeview window handle
'hItem - item's handle whose checkbox state is to be to returned
'
'Returns true if the item's state image is
'set to the checked checkbox index, returns
'false otherwise.
'---------------------------------------------------

Dim tvi as TVITEM

'Initialize the struct and get the item's state value.
With tvi
.mask = TVIF_STATE
.hItem = hItem
.stateMask = TVIS_STATEIMAGEMASK
End With

Call TreeView_GetItem(hwndTV, tvi)

'We have to test to see if the treeview
'checked state image *is* set since the logical
'And test on the unchecked image (1) will
'evaluate to true when either checkbox image
'is set.
IsTVItemChecked = (tvi.state And INDEXTOSTATEIMAGEMASK(IIL_CHECKED))

End Function


public Function IsTVItemCheckedFromClick(hwndTV as Long, _
X as Long, _
Y as Long) as Boolean

'---------------------------------------------------
'Determines if the current state image of the
'item under the specified point (if any) is
'set to the checked checkbox image index.
'
'hwndTV - treeview window handle
'x, y - treeview co-ordinates in which
' to retrieve the item from
'
'Returns true if the item's state image is
'set to the checked checkbox index, or false
'otherwise.
'---------------------------------------------------

Dim tvhti as TVHITTESTINFO
Dim fChecked as Boolean

tvhti.pt.X = X
tvhti.pt.Y = Y

If TreeView_HitTest(hwndTV, tvhti) then 'returns an hItem also

fChecked = IsTVItemChecked(hwndTV, tvhti.hItem)

'Since we retrieved the item's handle from
'a treeview co-ordinate as a result of a
'NodeClick event (or MouseUp event, both are
'invoked from a NM_CLICK notification), if
'this co-ordinate is within the area of the
'item's state icon, then the item's checkbox
'image is *in the process* of being toggled,
'but *not yet* toggled. So we'll toggle the
'return value reflecting the soon-to-be-set
'state value.
If (tvhti.flags And TVHT_ONITEMSTATEICON) then fChecked = Not fChecked

IsTVItemCheckedFromClick = fChecked

End If

End Function


public Function SetTVItemCheckImage(hwndTV as Long, _
hItem as Long, _
fCheck as Boolean) as Boolean

'---------------------------------------------------
'set the specified checkbox state for the
'specified item. Returns true if successful,
'returns false otherwise.
'
'hwndTV - treeview window handle
'hItem - item's handle whose checkbox state is to be to set
'fCheck - If true, sets the checkbox state to the checked image,
' if false, sets the unchecked image.
'---------------------------------------------------

Dim tvi as TVITEM

With tvi
.mask = TVIF_HANDLE Or TVIF_STATE
.hItem = hItem
.stateMask = TVIS_STATEIMAGEMASK

'as the values for the check constants are 1 for
'unchecked (IIL_UNCHECKED) and 2 for checked
'(IIL_CHECKED), fCheck (which is either true or
'false) can be used directly to toggle the
'INDEXTOIMAGESTATE parameter.
'
'This is accomplished by using the ABS() of
'fCheck (turning true (-1) and false (0)
'into 1 and 0 respectively.) Now, by adding 1,
'the value toggles between 2 and 1 respectively,
'exactly the same as using the IIL_ constants.
'
'Therefore, the single line of code below is
'equivalent to an If..then statement of:
'
'If fCheck then
' tvi.state = INDEXTOSTATEIMAGEMASK(IIL_CHECKED)
'else: tvi.state = INDEXTOSTATEIMAGEMASK(IIL_UNCHECKED)
'End If
'
'See the comments section for code that more
'clearly demonstrates using ABS() to achieve this.

.state = INDEXTOSTATEIMAGEMASK(Abs(fCheck) + 1)

End With

SetTVItemCheckImage = TreeView_SetItem(hwndTV, tvi)

End Function


public Function GetTVItemText(hwndTV as Long, _
hItem as Long, _
optional cbItem as Long = MAX_ITEM) as string

'---------------------------------------------
'Returns the text of the specified treeview
'item if successful, returns an empty string
'otherwise.
'
'hwndTV - treeview window handle
'hItem - item's handle whose text is to be to returned
'cbItem - length of the specified item's text.
'---------------------------------------------

Dim tvi as TVITEM

With tvi
.mask = TVIF_TEXT
.hItem = hItem
.pszText = string$(cbItem, 0)
.cchTextMax = cbItem
End With

If TreeView_GetItem(hwndTV, tvi) then
GetTVItemText = GetStrFromBufferA(tvi.pszText)
End If

End Function


public Function GetStrFromBufferA(item as string) as string

'Returns the string before first null char
'encountered (if any) from an ANSI string.

If InStr(item, vbNullChar) then
GetStrFromBufferA = Left$(item, InStr(item, vbNullChar) - 1)

else

'If item had no null char, the Left$ function
'above would return a zero length string ("").
GetStrFromBufferA = item

End If

End Function


public Function GetTVItemFromNode(hwndTV as Long, _
nod as Node) as Long


'If successful, returns the treeview item
'handle represented by the specified Node,
'returns 0 otherwise.

Dim nodeCur as Node
Dim asNodes() as string
Dim nNodes as Integer
Dim I as Integer
Dim hitemParent as Long
Dim hItem as Long

set nodeCur = nod

'Cache the node and all of it's parent
'node's text in the array
Do While (nodeCur is nothing) = false
nNodes = nNodes + 1

ReDim Preserve asNodes(nNodes)
asNodes(nNodes) = nodeCur.Text

set nodeCur = nodeCur.Parent
Loop

'get the hItem of the first root in the
'treeview, it will be the first parent
hitemParent = TreeView_GetRoot(hwndTV)

If hitemParent then

'Walk through the cached node text from
'the root to the specified node (backwards
'through the array)

Do While nNodes

'get the hItem of the current node
hItem = FindTVItemFromText(hwndTV, _
hitemParent, _
asNodes(nNodes))

If hItem then

'Make the the current parent's first
'child item the new parent
hitemParent = TreeView_GetChild(hwndTV, hItem)

else: Exit Function
End If

nNodes = nNodes - 1

Loop

GetTVItemFromNode = hItem

End If

End Function


public Function FindTVItemFromText(hwndTV as Long, _
byval hitemChild as Long, _
sItem as string) as Long

'---------------------------------------------
'Returns the first encountered item handle
'whose text label matches the specified text.
'*is case sensitive*.
'
'hwndTV - treeview window handle
'hitemChild - first sibling item's handle in which to search
'sItem - specified item's text we're looking for
'
'If the text represented by sItem is found, it's
'hItem is returned, otherwise 0 is returned.
'---------------------------------------------

'Can't find the hItem of an item with no text...
If len(sItem) = 0 then Exit Function

Do While hitemChild

'If the current sibling item label
'matches our target text, we're done.

If GetTVItemText(hwndTV, hitemChild, MAX_ITEM) = sItem then
FindTVItemFromText = hitemChild
Exit Function
End If

'Keep going while we have subsequent
'sibling items
hitemChild = TreeView_GetNextSibling(hwndTV, hitemChild)

Loop

End Function


public Function TreeView_HitTest(hwnd as Long, _
lpht as TVHITTESTINFO) as Long

'Determines the location of the specified point
'relative to the client area of a treeview control.
'Returns the handle to the tree-view item that
'occupies the specified point or null if no item
'occupies the point.

TreeView_HitTest = SendMessageAny(hwnd, TVM_HITTEST, 0&, lpht)

End Function


public Function TreeView_GetItem(hwnd as Long, pitem as TVITEM) as Boolean

'Retrieves some or all of a tree-view
'item's attributes. Returns true if
'successful or false otherwise.

TreeView_GetItem = SendMessageAny(hwnd, TVM_GETITEM, 0&, pitem)

End Function


public Function TreeView_SetItem(hwnd as Long, pitem as TVITEM) as Boolean

'Sets some or all of a tree-view item's
'attributes. Old docs say returns zero if
'successful or - 1 otherwise.
'new docs say returns true if successful,
'or false otherwise!

TreeView_SetItem = SendMessageAny(hwnd, TVM_SETITEM, 0&, pitem)

End Function


public Function INDEXTOSTATEIMAGEMASK(iState as Long) as Long

'Prepares the index of a state image so that a
'treeview control or listview control can use the
'index to retrieve the state image for an item.
'Returns the one-based index of the state image
'shifted left twelve bits. A common control
'utility macro.
'This macro is defined in Commctrl.h as:
'#define INDEXTOSTATEIMAGEMASK(i) ((i) << 12)

INDEXTOSTATEIMAGEMASK = iState * (2 ^ 12)

End Function


public Function TreeView_GetNextItem(hwnd as Long, _
hItem as Long, _
flag as Long) as Long

'Retrieves the tree-view item that bears the
'specified relationship to a specified item.
'Returns the handle to the item if successful
'or 0 otherwise.

TreeView_GetNextItem = SendMessageAny(hwnd, _
TVM_GETNEXTITEM, _
flag, _
byval hItem)

End Function


public Function TreeView_GetChild(hwnd as Long, hItem as Long) as Long

'Retrieves the first child item. The hitem
'parameter must be null. Returns the handle
'to the item if successful or 0 otherwise.

TreeView_GetChild = TreeView_GetNextItem(hwnd, hItem, TVGN_CHILD)

End Function


public Function TreeView_GetNextSibling(hwnd as Long, _
hItem as Long) as Long

'Retrieves the next sibling item.
'Returns the handle to the item if
'successful or 0 otherwise.

TreeView_GetNextSibling = TreeView_GetNextItem(hwnd, hItem, TVGN_NEXT)

End Function


public Function TreeView_GetRoot(hwnd as Long) as Long

'Retrieves the topmost or very first item
'of the tree-view control. Returns the handle
'to the item if successful or 0 otherwise.

TreeView_GetRoot = TreeView_GetNextItem(hwnd, 0, TVGN_ROOT)

End Function
'--end block--'