web development India freelance website designer
Demonstrates some serious goofing around with treeview item data...
For both the Mscomctl and Comctl32 TreeView and ListView controls, the Node and ListItem's ObjPtr values reside at the 3rd DWORD
(@ byte offset 8) in the Node and ListItem's lParam, i.e.:
MoveMemory pNode, ByVal tvi.lParam + 8, 4

' ...these aren't yet fully tested
'
' MoveMemory hItem, ByVal ObjPtr(Node) + 68, 4 ' Node's hItem is @ byte offset 68
' MoveMemory tvi.lParam, ObjPtr(Node) + 84, 4 ' Node's tvi.lParam is @ byte offset 84
' MoveMemory pNode, hItem + 4, 4 ' hItem's ObjPtr(Node) is @ byte offset 4

In the module:

Option Explicit
' Brad Martinez, http://www.mvps.org/ccrp/
' User-defined as the maximum treeview item text length.
' If an items text exceeds this value when calling GetTVItemText, there will be problems...
Public Const MAX_ITEM = 256

Public Const EM_SETTABSTOPS = &HCB

Declare Sub MoveMemory Lib "kernel32" Alias "RtlMoveMemory" (pDest As Any, pSource As Any, ByVal dwLength As Long)
Declare Function LocalSize Lib "kernel32" (ByVal hMem As Long) As Long

Declare Function lstrcpyA Lib "kernel32" (lpString1 As Any, lpString2 As Any) As Long
Declare Function lstrlenA Lib "kernel32" (lpString As Any) As Long
Declare Function lstrcpyW Lib "kernel32" (lpString1 As Any, lpString2 As Any) As Long
Declare Function lstrlenW Lib "kernel32" (lpString As Any) As Long

Declare Function SendMessage Lib "user32" Alias "SendMessageA" _
(ByVal hWnd As Long, ByVal wMsg As Long, wParam As Any, _
lParam As Any) As Long ' <---

Declare Function GetVersionEx Lib "kernel32" Alias "GetVersionExA" (lpVersionInformation _
As OSVERSIONINFO) As Long

Public Type OSVERSIONINFO
dwOSVersionInfoSize As Long
dwMajorVersion As Long
dwMinorVersion As Long
dwBuildNumber As Long
dwPlatformId As Long
szCSDVersion As String * 128 ' Maintenance string for PSS usage
End Type

Public Enum GVE_PlatformId
VER_PLATFORM_WIN32s = 0
VER_PLATFORM_WIN32_WINDOWS = 1
VER_PLATFORM_WIN32_NT = 2
End Enum

' what's in treeview hItems... i.e MoveMemory ti, ByVal hItem, Len(ti)
' very undocumented, but has been tested and is consistant in the following:
' Platform Win version IE verson Comctl32.dll version TREEITEM bytes
' Win95 4.00.950a 3.02 (4.70.1215) 4.00.950 32 bytes
' Win95 4.00.950a 3.02 (4.70.1215) 4.70 32 bytes
' NT4 SP3 4.00.1381 3.02 (4.70.1300) 4.70 32 bytes
' Win95 4.00.950a 4.01 (4.72.3118.8 SP1) 4.72.3110.1 36 bytes
' Win98 4,10.1998 4.72.3612.1713 (SP2) 4.72.3612.1702 36 bytes
' NT5 b2 5.00.1877 5.00.0708.700 5.00.0707.3000 36 bytes

#Const WIN32_IE = &H400

Public Type TREEITEM ' ti
hitemParent As Long ' handle of the item's parent, can be 0 (root's parent is a dummy
' item, whose only valid member is the hitemChild, the root itself)
hitemNextSibling As Long ' handle of the item's next sibling, can be 0
hitemChild As Long ' handle of the item's first child, can be 0
lpszText As Long ' pointer to the item's text, allocated in DWORD chunks, can be
' LPSTR_TEXTCALLBACK, is Unicode on NT
wState As Integer ' item's state flags, 1st byte is state, low nibble of 2nd byte is
' overlay image index, high nibble of 2nd byte is state image index
wImage As Integer ' normal icon imagelist index, can be I_IMAGECALLBACK (&HFFFF)
wSelectedImage As Integer ' selected icon imagelist index, can be I_IMAGECALLBACK (&HFFFF)
wID As Integer ' appears to be some sort of item ID (?)
wIndex As Integer ' item's 0-based physical position in the tree, can change
bLevel As Byte ' item's 0-based hierarchical level in the tree
bChildren As Byte ' TVITEM.cChildren, can't be I_CHILDRENCALLBACK (?)
lParam As Long ' TVITEM.lParam, usually points to something internally allocated
' / 32 bytes
#If (WIN32_IE >= &H400) Then
dwIDBit As Long ' always 1
#End If
End Type

' treeview definitions defined in Commctrl.h
' Callback constants

' T/LVITEM.pszText
Public Const LPSTR_TEXTCALLBACK = (-1)

' TVITEM.iImage/iSelectedImage, LVITEM.iImage
Public Const I_IMAGECALLBACK = (-1)

' TVITEM.cChildren
Public Const I_CHILDRENCALLBACK = (-1&)

Public Type TVITEM ' was TV_ITEM
mask As TVITEM_mask
hItem As Long
state As TVITEM_state
stateMask As TVITEM_state
pszText As Long ' pointer
cchTextMax As Long
iImage As Long
iSelectedImage As Long
cChildren As Long
lParam As Long
End Type

Public Enum TVITEM_mask
TVIF_TEXT = &H1
TVIF_IMAGE = &H2
TVIF_PARAM = &H4
TVIF_STATE = &H8
TVIF_HANDLE = &H10
TVIF_SELECTEDIMAGE = &H20
TVIF_CHILDREN = &H40
#If (WIN32_IE >= &H400) Then
TVIF_INTEGRAL = &H80
#End If
TVIF_DI_SETITEM = &H1000 ' Notification
End Enum

Public Enum TVITEM_state
TVIS_FOCUSED = &H1 ' no more than one item
TVIS_SELECTED = &H2 ' highlight, more than one?!
TVIS_CUT = &H4
TVIS_DROPHILITED = &H8
TVIS_BOLD = &H10
TVIS_EXPANDED = &H20
TVIS_EXPANDEDONCE = &H40
#If (WIN32_IE >= &H300) Then
TVIS_EXPANDPARTIAL = &H80
#End If
TVIS_OVERLAYMASK = &HF00
TVIS_STATEIMAGEMASK = &HF000
TVIS_USERMASK = &HF000
End Enum

' messages
Public Const TV_FIRST = &H1100
Public Const TVM_GETNEXTITEM = (TV_FIRST + 10)
Public Const TVM_GETITEM = (TV_FIRST + 12)
Public Const TVM_SETITEM = (TV_FIRST + 13)

Public Enum TVM_GETNEXTITEM_wParam
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

' Returns an ANSII string from a pointer to an ANSII string.
Public Function GetStrFromPtrA(lpszA As Long) As String
Dim sRtn As String
sRtn = String$(lstrlenA(ByVal lpszA), 0)
If Len(sRtn) Then
Call lstrcpyA(ByVal sRtn, ByVal lpszA)
GetStrFromPtrA = sRtn
End If
End Function

' Returns an ANSII string from a pointer to a Unicode string.
Public Function GetStrFromPtrW(lpszW As Long) As String
Dim sRtn As String
sRtn = String$(lstrlenW(ByVal lpszW) * 2, 0) ' 2 bytes/char
If Len(sRtn) Then
Call lstrcpyW(ByVal sRtn, ByVal lpszW)
GetStrFromPtrW = StrConv(sRtn, vbFromUnicode)
End If
End Function

' Returns the string before first null char encountered (if any) from an ANSII string.
Public Function GetStrFromBufferA(sz As String) As String
If InStr(sz, vbNullChar) Then
GetStrFromBufferA = Left$(sz, InStr(sz, vbNullChar) - 1)
Else
' If sz had no null char, the Left$ function above would return a zero length string ("").
GetStrFromBufferA = sz
End If
End Function

' Returns True if the current operating system is WinNT
Public Function IsWinNT() As Boolean
Dim osvi As OSVERSIONINFO
osvi.dwOSVersionInfoSize = Len(osvi)
GetVersionEx osvi
IsWinNT = (osvi.dwPlatformId = VER_PLATFORM_WIN32_NT)
End Function

' treeview calls
' Returns the lParam of the specified treeview item.
Public Function GetTVItemlParam(hwndTV As Long, hItem As Long) As Long
Dim tvi As TVITEM
tvi.mask = TVIF_PARAM
tvi.hItem = hItem
If TreeView_GetItem(hwndTV, tvi) Then
GetTVItemlParam = tvi.lParam
End If
End Function

' Returns the text of the specified treeview item if successful, returns an empty string otherwise.
' hwndTV - treeview's window handle
' hItem - item's handle whose text is to be to returned
' cbItem - length of the specified item's text.
Public Function GetTVItemText(hwndTV As Long, hItem As Long, _
Optional cbItem As Long = MAX_ITEM) As String
Dim tvi As TVITEM
' Initialize the struct to retrieve the item's text.
tvi.mask = TVIF_TEXT
tvi.hItem = hItem
tvi.pszText = StrPtr(String$(cbItem, 0))
tvi.cchTextMax = cbItem
If TreeView_GetItem(hwndTV, tvi) Then
GetTVItemText = GetStrFromPtrA(tvi.pszText)
End If
End Function

' Returns the specified treeview item's TVITEM.cChildren value
' hwndTV - treeview's window handle
' hItem - handle of the item to evaluate
Public Function GetTVItemChildren(hwndTV As Long, hItem As Long) As Long
Dim tvi As TVITEM
tvi.mask = TVIF_CHILDREN
tvi.hItem = hItem
Call TreeView_GetItem(hwndTV, tvi)
GetTVItemChildren = tvi.cChildren
End Function

' Treeview macros defined in Commctrl.h

' Retrieves some or all of a tree-view item's attributes.
' Returns TRUE if successful or FALSE otherwise.
Public Function TreeView_GetItem(hWnd As Long, pitem As TVITEM) As Boolean
TreeView_GetItem = SendMessage(hWnd, TVM_GETITEM, 0, pitem)
End Function

' 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
Public Function TreeView_SetItem(hWnd As Long, pitem As TVITEM) As Boolean
TreeView_SetItem = SendMessage(hWnd, TVM_SETITEM, 0, pitem)
End Function

' TreeView_GetNextItem
' 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.
Public Function TreeView_GetNextItem(hWnd As Long, hItem As Long, flag As Long) As Long
TreeView_GetNextItem = SendMessage(hWnd, TVM_GETNEXTITEM, ByVal flag, ByVal hItem)
End Function

' Retrieves the first child item. The hitem parameter must be NULL.
' Returns the handle to the item if successful or 0 otherwise.
Public Function TreeView_GetChild(hWnd As Long, hItem As Long) As Long
TreeView_GetChild = TreeView_GetNextItem(hWnd, hItem, TVGN_CHILD)
End Function

' Retrieves the next sibling item.
' Returns the handle to the item if successful or 0 otherwise.
Public Function TreeView_GetNextSibling(hWnd As Long, hItem As Long) As Long
TreeView_GetNextSibling = TreeView_GetNextItem(hWnd, hItem, TVGN_NEXT)
End Function

' Retrieves the previous sibling item.
' Returns the handle to the item if successful or 0 otherwise.
Public Function TreeView_GetPrevSibling(hWnd As Long, hItem As Long) As Long
TreeView_GetPrevSibling = TreeView_GetNextItem(hWnd, hItem, TVGN_PREVIOUS)
End Function

' Retrieves the parent of the specified item.
' Returns the handle to the item if successful or 0 otherwise.
Public Function TreeView_GetParent(hWnd As Long, hItem As Long) As Long
TreeView_GetParent = TreeView_GetNextItem(hWnd, hItem, TVGN_PARENT)
End Function

' Retrieves the first visible item.
' Returns the handle to the item if successful or 0 otherwise.
Public Function TreeView_GetFirstVisible(hWnd As Long) As Long
TreeView_GetFirstVisible = TreeView_GetNextItem(hWnd, 0, TVGN_FIRSTVISIBLE)
End Function

' Retrieves the next visible item that follows the specified item. The specified item must be visible.
' Use the TVM_GETITEMRECT message to determine whether an item is visible.
' Returns the handle to the item if successful or 0 otherwise.
Public Function TreeView_GetNextVisible(hWnd As Long, hItem As Long) As Long
TreeView_GetNextVisible = TreeView_GetNextItem(hWnd, hItem, TVGN_NEXTVISIBLE)
End Function

' Retrieves the first visible item that precedes the specified item. The specified item must be visible.
' Use the TVM_GETITEMRECT message to determine whether an item is visible.
' Returns the handle to the item if successful or 0 otherwise.
Public Function TreeView_GetPrevVisible(hWnd As Long, hItem As Long) As Long
TreeView_GetPrevVisible = TreeView_GetNextItem(hWnd, hItem, TVGN_PREVIOUSVISIBLE)
End Function

' Retrieves the currently selected item.
' Returns the handle to the item if successful or 0 otherwise.
Public Function TreeView_GetSelection(hWnd As Long) As Long
TreeView_GetSelection = TreeView_GetNextItem(hWnd, 0, TVGN_CARET)
End Function

' Retrieves the item that is the target of a drag-and-drop operation.
' Returns the handle to the item if successful or 0 otherwise.
Public Function TreeView_GetDropHilight(hWnd As Long) As Long
TreeView_GetDropHilight = TreeView_GetNextItem(hWnd, 0, TVGN_DROPHILITE)
End Function

' Retrieves the topmost or very first item of the tree-view control.
' Returns the handle to the item if successful or 0 otherwise.
Public Function TreeView_GetRoot(hWnd As Long) As Long
TreeView_GetRoot = TreeView_GetNextItem(hWnd, 0, TVGN_ROOT)
End Function

'Code in Form1.frm

Option Explicit
Private m_hwndTV As Long

Private Sub Form_Load()
Dim Node1 As Node
Dim Node2 As Node
Dim Node3 As Node
Dim i As Integer
Dim j As Integer
Dim k As Integer
' number of Nodes at each respective hierarchical level
Const nNodes1 = 2
Const nNodes2 = 3
Const nNodes3 = 3
Call SendMessage(Text1.hWnd, EM_SETTABSTOPS, ByVal 1, 60)
With TreeView1
' Initialize the TreeView
.HideSelection = False
.Indentation = 19 * Screen.TwipsPerPixelX
.LabelEdit = tvwManual
.LineStyle = tvwRootLines
m_hwndTV = .hWnd
' Fill up the treeview...
For i = 1 To nNodes1
Set Node1 = .Nodes.Add(, , , "Root" & i, 1, 1)
For j = 1 To nNodes2
Set Node2 = .Nodes.Add(Node1.Index, tvwChild, , "Root" & i & "Child" & j, 2, 2)
For k = 1 To nNodes3
Set Node3 = .Nodes.Add(Node2.Index, tvwChild, , _
"GrandChild" & (nNodes2 * nNodes3 * (i - 1)) + (nNodes3 * (j - 1)) + k, 3, 3)
Next
Next
Node1.Expanded = True
Next
.Nodes(1).Selected = True
Call TreeView1_NodeClick(.Nodes(1))
End With
End Sub

Private Sub TreeView1_NodeClick(ByVal Node As ComctlLib.Node)
Dim hItem As Long
Dim ti As TREEITEM
Dim sOut As String
hItem = TreeView_GetSelection(m_hwndTV)
If hItem Then
MoveMemory ti, ByVal hItem, Len(ti)
With ti
' The root's parent hItem points to a dummy hItem, whose
' only valid TREEITEM member is hitemChild, the root itself.
sOut = GetTVItemText(m_hwndTV, .hitemParent)
If Len(sOut) Then
sOut = "hitemParent:" & vbTab & sOut & vbCrLf
Else
sOut = "hitemParent:" & vbTab & "" & vbCrLf
End If
If .hitemNextSibling Then
sOut = sOut & "hitemNextSibling:" & vbTab & GetTVItemText(m_hwndTV, _
.hitemNextSibling) & vbCrLf
Else
sOut = sOut & "hitemNextSibling:" & vbTab & "" & vbCrLf
End If
If .hitemChild Then
sOut = sOut & "hitemChild:" & vbTab & GetTVItemText(m_hwndTV, _
.hitemChild) & vbCrLf
Else
sOut = sOut & "hitemChild:" & vbTab & "" & vbCrLf
End If
If (.lpszText = LPSTR_TEXTCALLBACK) Then
sOut = sOut & "lpszText:" & vbTab & "LPSTR_TEXTCALLBACK" & vbCrLf
Else
If IsWinNT Then
sOut = sOut & "lpszText:" & vbTab & GetStrFromPtrW(.lpszText) & vbCrLf
Else
sOut = sOut & "lpszText:" & vbTab & GetStrFromPtrA(.lpszText) & vbCrLf
End If
End If
sOut = sOut & "wState" & vbTab & "&H" & Hex(.wState) & vbCrLf
If (.lpszText = I_IMAGECALLBACK) Then
sOut = sOut & "wImage:" & vbTab & "I_IMAGECALLBACK" & vbCrLf
Else
sOut = sOut & "wImage:" & vbTab & .wImage & vbCrLf
End If
If (.lpszText = I_IMAGECALLBACK) Then
sOut = sOut & "wSelectedImage:" & vbTab & "I_IMAGECALLBACK" & vbCrLf
Else
sOut = sOut & "wSelectedImage:" & vbTab & .wSelectedImage & vbCrLf
End If
sOut = sOut & "wID:" & vbTab & .wID & vbCrLf
sOut = sOut & "wIndex:" & vbTab & .wIndex & vbCrLf
sOut = sOut & "bLevel:" & vbTab & .bLevel & vbCrLf
sOut = sOut & "bChildren:" & vbTab & .bChildren & vbCrLf
sOut = sOut & "lParam size:" & vbTab & LocalSize(.lParam) & vbCrLf
#If (WIN32_IE >= &H400) Then
' valid only for Comctl32.dll >= v4.71
sOut = sOut & "dwIDBit:" & vbTab & "&H" & Hex(.dwIDBit) & " bytes"
#End If
End With ' ti
Text1 = sOut
End If ' hItem
End Sub

Private Sub Command1_Click()
Static fRemoveCallbacks As Boolean
fRemoveCallbacks = Not fRemoveCallbacks
Call SetNodeCallbacks(TreeView_GetRoot(m_hwndTV), fRemoveCallbacks)
Call TreeView1_NodeClick(TreeView1.SelectedItem)
End Sub

' Recursively walks the whole tree, toggling the callback attributes (text, images, button) for all Nodes in the VB TreeView's real
treeview, as specified by the fRemove flag.. The TreeView normally does callback for these items, but can be explicitly set and
overridden (and the VB TreeView has no idea what's happening).
' On first call, pass TreeView_GetRoot for hitemSib

Private Sub SetNodeCallbacks(hitemSib As Long, fRemove As Boolean)
Dim tvi As TVITEM
Dim nod As Node
tvi.mask = TVIF_TEXT Or TVIF_IMAGE Or TVIF_SELECTEDIMAGE ' Or TVIF_CHILDREN
Do While hitemSib
' test code, uncomment for the Immediate and Locals window
'Debug.Print GetTVItemChildren(m_hwndTV, hitemSib)
'Call InvestigateTVItemData(m_hwndTV, hitemSib)
tvi.hItem = hitemSib
If fRemove Then
' Get the Node from the hItem, and remove the item's
' callback attributes by explicitly setting them.
Set nod = GetNodeFromhItem(hitemSib)
If ((nod Is Nothing) = False) Then
' Store the Node's Text in an allocated pointer'
tvi.pszText = StrPtr(String$(MAX_ITEM, 0))
Call lstrcpyA(ByVal tvi.pszText, ByVal nod.Text)
' real imagelist indices are zero-based
tvi.iImage = nod.Image - 1
tvi.iSelectedImage = CLng(nod.SelectedImage) - 1
' see below...
' tvi.cChildren = Abs(CBool(TreeView_GetChild(m_hwndTV, hitemSib)))
End If
Else
' Restore the callbacks
tvi.pszText = LPSTR_TEXTCALLBACK
tvi.iImage = I_IMAGECALLBACK
tvi.iSelectedImage = I_IMAGECALLBACK
' this causes problems, something's weird here that has yet to be understood...
' tvi.cChildren = I_CHILDRENCALLBACK
End If
Call TreeView_SetItem(m_hwndTV, tvi)
' Recursively call this proc using the current sibling's first child (if any), and get the next sibling
Call SetNodeCallbacks(TreeView_GetChild(m_hwndTV, hitemSib), fRemove)
hitemSib = TreeView_GetNextSibling(m_hwndTV, hitemSib)
Loop
End Sub

Private Function GetNodeFromhItem(hItem As Long) As Node
Dim lParam As Long
Dim pNode As Long
lParam = GetTVItemlParam(m_hwndTV, hItem)
If lParam Then
MoveMemory pNode, ByVal lParam + 8, 4
Set GetNodeFromhItem = GetNodeFromPtr(pNode)
End If ' lParam
End Function

Private Function GetNodeFromPtr(pNode As Long) As Node
Dim nod As Node
MoveMemory nod, pNode, 4
Set GetNodeFromPtr = nod
MoveMemory nod, 0&, 4
End Function

Public Function InvestigateTVItemData(hwndTV As Long, hItem As Long) As Boolean
Dim nod As Node
Dim lParam As Long
Dim adw0(24) As Long
Dim adw1(24) As Long
Dim adw2(24) As Long
Dim adw3(24) As Long
Dim adw4(24) As Long
Set nod = GetNodeFromhItem(hItem)
lParam = GetTVItemlParam(m_hwndTV, hItem)
MoveMemory adw0(0), ByVal ObjPtr(nod), 100 ' Node's hItem is in adw0(17) (@ byte offset 68)
MoveMemory adw1(0), ObjPtr(nod), 100 ' Node's tvi.lParam is in adw1(21) (@ byte offset 84)
MoveMemory adw2(0), ByVal lParam, 100 ' tvi.lParam's pNode is in adw2(2) (@ byte offset 8)
MoveMemory adw3(0), ByVal hItem, 100 ' hItem's tvi.lParam's is in adw3(7) (@ byte offset 28)
MoveMemory adw4(0), hItem, 100 ' hItem's ObjPtr(Node) is in adw4(1) (@ byte offset 4)
Stop
End Function

' Determines if the given treeview item handle is valid and exists in the specified treeview.
' The hItem is valid if it equals the child (@ byte offset 8), or child's sibling
' (@ byte offset 4), of the hItem's parent (@ byte offset 0)
Public Function IsTVItemValid(hwndTV As Long, hItem As Long) As Boolean
Dim hitemParent As Long
Dim hitemChild As Long
Dim fValid As Boolean
If (LocalSize(hItem) >= 32) Then
' Get the item's parent (the root has a dummy parent hItem)
MoveMemory hitemParent, ByVal hItem, 4
' Get the parent's first child
MoveMemory hitemChild, ByVal hitemParent + 8, 4
Do While hitemChild And (fValid = False)
fValid = (hItem = hitemChild)
' Get the current sibling's next sibling
MoveMemory hitemChild, ByVal hitemChild + 4, 4
Loop
End If ' LocalSize
IsTVItemValid = fValid
End Function
TreeView Item Data

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