vbAccelerator - Contents of code file: cTreeViewMultiSelect.cls

VERSION 1.0 CLASS
BEGIN
  MultiUse = -1  'True
END
Attribute VB_Name = "cTreeViewMultiSelect"
Attribute VB_GlobalNameSpace = False
Attribute VB_Creatable = True
Attribute VB_PredeclaredId = False
Attribute VB_Exposed = False
Option Explicit

Private m_cNodeSelectionRoot As cTreeViewNode
Private m_colSelected As New Collection
Private m_lastSelectedItem  As cTreeViewNode
Private m_bSelectionChanged As Boolean
Private WithEvents m_tvw As vbalTreeView
Attribute m_tvw.VB_VarHelpID = -1

Private Declare Function GetAsyncKeyState Lib "user32" (ByVal vKey As Long) As
 Integer

Public Property Get SelectionCount() As Long
   SelectionCount = m_colSelected.count
End Property
Public Property Get SelectedNode(ByVal lIndex As Long) As cTreeViewNode
   Set SelectedNode = m_colSelected(lIndex)
End Property

Public Sub Attach(tvw As vbalTreeView)
   Set m_tvw = tvw
End Sub
Public Sub Detach()
   Set m_tvw = Nothing
   Set m_colSelected = Nothing
End Sub

Private Sub SelectBetween(tvw As vbalTreeView, node1 As cTreeViewNode, node2 As
 cTreeViewNode)
Dim bInSelection As Boolean
Dim bNoneFoundYet As Boolean
Dim nodStart As cTreeViewNode
Dim sKey1 As String
Dim sKey2 As String
   Set m_colSelected = New Collection
   Set nodStart = tvw.nodes(1)
   sKey1 = node1.Key
   sKey2 = node2.Key
   iterateSelectBetween nodStart, sKey1, sKey2, bInSelection, True
End Sub
Private Sub iterateSelectBetween(nodStart As cTreeViewNode, ByVal sKey1 As
 String, ByVal sKey2 As String, ByRef bInSelection As Boolean, ByRef
 bNoneFoundYet As Boolean)
   
   Do While Not (nodStart Is Nothing)
      If Not (bInSelection) Then
         If (bNoneFoundYet) Then
            If (nodStart.Key = sKey1) Then
               bInSelection = True
               bNoneFoundYet = False
            ElseIf (nodStart.Key = sKey2) Then
               Dim sKeySwap As String
               sKeySwap = sKey2
               sKey2 = sKey1
               sKey1 = sKeySwap
               bInSelection = True
               bNoneFoundYet = False
            End If
         End If
      End If
      NodeSelected(nodStart) = bInSelection
      If (bInSelection) Then
         If (nodStart.Key = sKey2) Then
            bInSelection = False
         End If
      End If
      If (nodStart.Expanded And nodStart.Children.count > 0) Then
         iterateSelectBetween nodStart.Children(1), sKey1, sKey2, bInSelection,
          bNoneFoundYet
      End If
      Set nodStart = nodStart.NextSibling
   Loop
   
End Sub

Public Property Get NodeSelected(node As cTreeViewNode) As Boolean
Dim nodSel As cTreeViewNode
   On Error Resume Next
   Set nodSel = m_colSelected(node.Key)
   On Error GoTo 0
   If Not (nodSel Is Nothing) Then
      NodeSelected = (nodSel.BackColor = vbHighlight)
   End If
End Property
Public Property Let NodeSelected(node As cTreeViewNode, ByVal bState As Boolean)
Dim nodAlready As cTreeViewNode
   
   On Error Resume Next
   Set nodAlready = m_colSelected(node.Key)
   On Error GoTo 0
   
   If (bState) Then
      If (nodAlready Is Nothing) Then
         m_colSelected.Add node, node.Key
         node.BackColor = vbHighlight
         node.ForeColor = vbHighlightText
         node.MouseOverBackColor = vbHighlight
         node.MouseOverForeColor = vbHighlightText
         node.SelectedMouseOverBackColor = vbHighlight
         node.SelectedMouseOverForeColor = vbHighlightText
         node.SelectedBackColor = vbHighlight
         node.SelectedForeColor = vbHighlightText
         node.SelectedNoFocusBackColor = vbHighlight
         node.SelectedNoFocusForeColor = vbHighlightText
         node.Text = node.Text
      End If
   Else
      If Not (nodAlready Is Nothing) Then
         m_colSelected.Remove nodAlready.Key
         node.BackColor = vbWindowBackground
         node.ForeColor = vbWindowText
         node.MouseOverBackColor = vbWindowBackground
         node.MouseOverForeColor = vbWindowText
         node.SelectedMouseOverBackColor = vbWindowBackground
         node.SelectedMouseOverForeColor = vbWindowText
         node.SelectedBackColor = vbWindowBackground
         node.SelectedForeColor = vbWindowText
         node.SelectedNoFocusBackColor = vbWindowBackground
         node.SelectedNoFocusForeColor = vbWindowText
         node.Text = node.Text
      End If
   End If
End Property


Private Sub m_tvw_KeyDown(KeyCode As Integer, Shift As Integer)
   If (KeyCode = vbKeyReturn) Or (KeyCode = vbKeySpace) Then
      If Not (m_tvw.SelectedItem Is Nothing) Then
         m_tvw.SelectedItem.Expanded = Not (m_tvw.SelectedItem.Expanded)
      End If
      KeyCode = 0
   End If
   m_bSelectionChanged = False
End Sub

Private Sub m_tvw_MouseDown(Button As Integer, Shift As Integer, x As Single, y
 As Single)
   
   ' Note we only need to do this on MouseDown, since
   ' the TreeView uses the Control key to allow scrolling
   ' when the mouse is not clicked.
   If (Shift And vbCtrlMask) = vbCtrlMask Then
      If Not (m_bSelectionChanged) Then
         If Not (m_lastSelectedItem Is Nothing) Then
            NodeSelected(m_lastSelectedItem) = Not
             (NodeSelected(m_lastSelectedItem))
         End If
      End If
   End If
   m_bSelectionChanged = False
   
End Sub

Private Sub m_tvw_SelectedNodeChanged()
Dim nodSelected As cTreeViewNode
   
   '
   m_bSelectionChanged = True
   Set m_lastSelectedItem = m_tvw.SelectedItem
   
   If Not (GetAsyncKeyState(vbKeyControl) = 0) Then
      ' Invert selection state for this node:
      If Not (m_lastSelectedItem Is Nothing) Then
         NodeSelected(m_lastSelectedItem) = Not
          (NodeSelected(m_lastSelectedItem))
      End If
   ElseIf Not (GetAsyncKeyState(vbKeyShift) = 0) Then
      ' Ensure all items between m_cNodeSelectionRoot and m_lastSelectedItem
      ' are selected, and anything else is not selected.
      If Not (m_cNodeSelectionRoot Is Nothing) Then
         If Not (m_lastSelectedItem Is Nothing) Then
            SelectBetween m_tvw, m_cNodeSelectionRoot, m_lastSelectedItem
         End If
      End If
   Else
      ' Clear anything that's selected
      For Each nodSelected In m_colSelected
         NodeSelected(nodSelected) = False
      Next
      Set m_colSelected = New Collection
      Set m_cNodeSelectionRoot = m_lastSelectedItem
      ' Select this item if necessary
      If Not (m_cNodeSelectionRoot Is Nothing) Then
         NodeSelected(m_cNodeSelectionRoot) = True
      End If
   End If
   '

End Sub