This method is intended for Visual Basic 5 or Visual Basic
6 where the Common Control library used is the MSComCtl 5 version (comctl32.ocx). Because the VB6-specific mscomctl.ocx (Common Controls 6)
is an implementation of the comctl32.dll control and not reliant on the version of comctl32.dll installed, this routine may not work when
applied to a ListView created from the VB6-specific mscomctl.ocx.
This enhanced Comctl32 functionality is only available to users with
comctl32.dll version 4.72 or greater installed, typically installed with IE4.x or greater, or with Win98. |
Many
people erroneously believe that the 'control' used in displaying hierarchical data such as Outlook Express' news reader view is a treeview
control with columns. Actually, the control is a ListView taking advantage of the comctl version 4-specific Indent member of the LV_ITEM
structure. This page shows how to add this functionality to a comctl32-based ListView (see Prerequisites above).
In addition, it demonstrates how to adjust the column indent for a
selected item either programmatically or under a user's control. Not demonstrated is the 'other' side of the news reader feature set -
expanding and collapsing the items subordinate to the thread.
Note: this method requires that an imagelist be assigned to the
control, even if its images are not used. |
Option Explicit
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
' Copyright ©1996-2011 VBnet/Randy Birch, All Rights Reserved.
' Some pages may also contain other copyrights by the author.
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
' Distribution: You can freely use this code in your own
' applications, but you may not reproduce
' or publish this code on any web site,
' online service, or distribute as source
' on any media without express permission.
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
Public Const LVIF_INDENT As Long = &H10
Public Const LVIF_TEXT As Long = &H1
Public Const LVS_EX_FULLROWSELECT As Long = &H20
Public Const LVM_FIRST As Long = &H1000
Public Const LVM_GETITEM As Long = (LVM_FIRST + 5)
Public Const LVM_SETITEM As Long = (LVM_FIRST + 6)
Public Const LVM_DELETEALLITEMS As Long = (LVM_FIRST + 9)
Public Const LVM_SETEXTENDEDLISTVIEWSTYLE As Long = (LVM_FIRST + 54)
Public Const LVM_GETEXTENDEDLISTVIEWSTYLE As Long = (LVM_FIRST + 55)
Public Const ICC_LISTVIEW_CLASSES As Long = &H1
Public Type LV_ITEM
mask As Long
iItem As Long
iSubItem As Long
state As Long
stateMask As Long
pszText As String
cchTextMax As Long
iImage As Long
lParam As Long
iIndent As Long
End Type
Public Type tagINITCOMMONCONTROLSEX
dwSize As Long
dwICC As Long
End Type
Public Declare Sub InitCommonControls Lib "comctl32" ()
Public Declare Function InitCommonControlsEx Lib "comctl32" _
(lpInitCtrls As tagINITCOMMONCONTROLSEX) As Boolean
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 LockWindowUpdate Lib "user32" _
(ByVal hwndLock As Long) As Long
Public Declare Function UpdateWindow Lib "user32" _
(ByVal hWnd As Long) As Long
Public Function InitComctl32(dwFlags As Long) As Boolean
Dim icc As tagINITCOMMONCONTROLSEX
On Error GoTo Err_OldVersion
icc.dwSize = Len(icc)
icc.dwICC = dwFlags
'VB will generate error 453 "Specified
'DLL function not found" here if the new
'version isn't installed and it can't find
'the function's name. We'll hopefully be
'able to load the old version below.
InitComctl32 = InitCommonControlsEx(icc)
Exit Function
Err_OldVersion:
InitCommonControls
End Function
|
Option Explicit
Private Sub Form_Load()
With ListView1
.SortKey = 0
.SmallIcons = ImageList1
.ColumnHeaders(1).Width = .Width - 600
.View = lvwReport
End With
Call InitComctl32(ICC_LISTVIEW_CLASSES)
Call SendMessage(ListView1.hWnd, _
LVM_SETEXTENDEDLISTVIEWSTYLE, _
LVS_EX_FULLROWSELECT, ByVal True)
End Sub
Private Sub Form_QueryUnload(Cancel As Integer, UnloadMode As Integer)
Call LockWindowUpdate(ListView1.hWnd)
Call SendMessage(ListView1.hWnd, LVM_DELETEALLITEMS, 0&, ByVal 0&)
Call LockWindowUpdate(0&)
End Sub
Private Sub Command1_Click()
'be sure to change the imgKey value to the
'key you've assigned to your list image(s)
LVLoadIndentDemo imgKey:="windows", Indent:=0
LVLoadIndentDemo imgKey:="page", Indent:=1
LVLoadIndentDemo imgKey:="pagecyan", Indent:=2
LVLoadIndentDemo imgKey:="pagecyan", Indent:=2
LVLoadIndentDemo imgKey:="page", Indent:=1
LVLoadIndentDemo imgKey:="pagecyan", Indent:=2
LVLoadIndentDemo imgKey:="cyanclip", Indent:=3
LVLoadIndentDemo imgKey:="yellowclip", Indent:=4
LVLoadIndentDemo imgKey:="yellowclip", Indent:=5
LVLoadIndentDemo imgKey:="yellowclip", Indent:=6
Exit Sub
'a different arrangement
LVLoadIndentDemo imgKey:="page", Indent:=0
LVLoadIndentDemo imgKey:="yellowclip", Indent:=1
LVLoadIndentDemo imgKey:="cyanclip", Indent:=2
LVLoadIndentDemo imgKey:="windows", Indent:=3
LVLoadIndentDemo imgKey:="yellowclip", Indent:=1
LVLoadIndentDemo imgKey:="cyanclip", Indent:=2
LVLoadIndentDemo imgKey:="windows", Indent:=3
LVLoadIndentDemo imgKey:="yellowclip", Indent:=4
LVLoadIndentDemo imgKey:="cyanclip", Indent:=5
LVLoadIndentDemo imgKey:="windows", Indent:=6
LVLoadIndentDemo imgKey:="page", Indent:=7
LVLoadIndentDemo imgKey:="yellowclip", Indent:=8
End Sub
Private Sub Command2_Click()
Unload Me
End Sub
Private Sub UpDown1_DownClick()
MoveListItem CLng(ListView1.SelectedItem.Index), -1
End Sub
Private Sub UpDown1_UpClick()
MoveListItem CLng(ListView1.SelectedItem.Index), 1
End Sub
Private Sub MoveListItem(hIndex As Long, direction As Long)
Dim newIndent As Long
Dim LV As LV_ITEM
'set the LV_ITEM mask and item index
LV.mask = LVIF_INDENT
LV.iItem = hIndex - 1 'subtract 1 as control is 0-based
'retrieve the current settings
Call SendMessage(ListView1.hWnd, LVM_GETITEM, 0&, LV)
'just add the direction passed to calculate
'the new indent position. Adding a negative
'number is the same as subtracting.
newIndent = LV.iIndent + direction
'if the new position is not less than the edge..
If newIndent >= 0 Then
'assign the new indent
LV.iIndent = newIndent
'set the new item indent
Call SendMessage(ListView1.hWnd, LVM_SETITEM, 0&, LV)
'change the item caption to reflect the new indent
ListView1.SelectedItem.Text = _
"This string is indented " & LV.iIndent & " level(s)"
End If
End Sub
Private Sub LVLoadIndentDemo(imgKey As String, Indent As Long)
Dim itmX As ListItem
Dim imgX As ListImage
Dim LV As LV_ITEM
Dim nItem As Long
Dim sItem As String
'add the item
sItem = "This string is indented " & Indent & " level(s)"
Set itmX = ListView1.ListItems.Add(, , Trim$(sItem))
'add the icon
If Len(imgKey) > 0 Then
itmX.SmallIcon = ImageList1.ListImages(imgKey).Key
End If
'if indentation is indicated
If Indent Then
'this is the item to indent (in this
'routine, the newly-added item)
nItem = CLng(itmX.Index)
'set up the structure
With LV
.mask = LVIF_INDENT
.iItem = nItem - 1 '0-based, so have to subtract 1
.iIndent = Indent
End With
'indent the item
Call SendMessage(ListView1.hWnd, LVM_SETITEM, 0&, LV)
End If
End Sub
|