Visual Basic Common Control API Routines
SendMessage: Determine Selected ListView ListItems
Posted:   Monday September 16, 2002
Updated:   Monday December 26, 2011
Applies to:   VB4-32, VB5, VB6
Developed with:   VB6, Windows XP
OS restrictions:   None
Author:   VBnet - Randy Birch
Related:   SendMessage: Determine a ListView's Visible Item Count
SendMessage: Clicking ListView White Space to De-select Items
SendMessage: ListView Select / Deselect All
This code is equally applicable to the VB4-32, VB5 and VB6 Listview controls.

A quick routine to demonstrate using SendMessage with LVM_GETSELECTEDCOUNT and LVM_GETNEXTITEM messages to traverse a listview to retrieve the indices to the selected items in a MultiSelect control. Also contains a portion of the LVM_SUBITEMHITTEST code from SendMessage: Clicking ListView White Space to De-select Items showing how to deselect items completely.

The results from the routine are used to populate an array containing the selected item indices; the list box in this demo shows the final contents of the selection array.

 BAS Module Code

 Form Code
Add a command button (Command1), a listview (Listview1), a list box (List1) and a label (Label1), with the following code:

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.
Private Const LVM_FIRST As Long = &H1000
Private Const LVM_SUBITEMHITTEST As Long = (LVM_FIRST + 57)
Private Const LVM_HITTEST As Long = (LVM_FIRST + 18)

Private Const LVM_GETNEXTITEM  As Long = (LVM_FIRST + 12)

Private Const LVHT_ABOVE = &H8
Private Const LVHT_BELOW = &H10
Private Const LVHT_TORIGHT = &H20
Private Const LVHT_TOLEFT = &H40
Private Const LVHT_NOWHERE As Long = &H1
Private Const LVHT_ONITEMICON As Long = &H2
Private Const LVHT_ONITEMLABEL As Long = &H4
Private Const LVHT_ONITEMSTATEICON As Long = &H8
                                    LVHT_ONITEMLABEL Or _

Private Type POINTAPI
   x As Long
   y As Long
End Type

   flags As Long
   iItem As Long
   iSubItem  As Long
End Type

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

Private Sub Form_Load()

   Dim itmx As ListItem
   Dim cnt As Long
   Dim tmp As Long
   Randomize Timer
   With ListView1
      .ColumnHeaders.Add , , "Name"
      .ColumnHeaders.Add , , "Size"
      .ColumnHeaders.Add , , "Type"
      .ColumnHeaders.Add , , "Created"
      .View = lvwReport
      .FullRowSelect = True 'VB6 only!
      For cnt = 1 To 100
        'create a few random entries
        'to simulate real data
         tmp = Int(Rnd(20) * 20) + 1
         Set itmx = .ListItems.Add(, , String(tmp, Chr$(123 - tmp)))       
         itmx.SubItems(1) = tmp & " kb"
         itmx.SubItems(2) = "winzip file"
         itmx.SubItems(3) = DateAdd("d", -Int(Rnd(365) * 365), Date)
   End With
End Sub

Private Sub Command1_Click()

   Const LVNI_SELECTED = &H2
   Dim nSelected() As Long
   Dim index As Long
   Dim numSelected As Long
   Dim cnt As Long

   numSelected = ListView_GetSelectedCount(ListView1.hwnd)

   If numSelected <> 0 Then
      ReDim nSelected(0 To numSelected - 1)
         index = ListView_GetNextItem(ListView1.hwnd, index, LVNI_SELECTED)
         If index > -1 Then          
            nSelected(cnt) = index
           cnt = cnt + 1
         End If
      Loop Until index = -1
     'debug only: print results to the list
      For cnt = 0 To numSelected - 1
         List1.AddItem nSelected(cnt)
   End If

End Sub

Private Sub ListView1_MouseDown(Button As Integer, _
                                Shift As Integer, _
                                x As Single, _
                                y As Single)

   Dim itemIndex As Long
  'Fill a HITTESTINFO structure with
  'information about the point in the
  'listview where the mouse was clicked.
   With hti
      .pt.x = (x / Screen.TwipsPerPixelX)
      .pt.y = (y / Screen.TwipsPerPixelY)
      .flags = LVHT_ABOVE Or LVHT_BELOW Or _
               LVHT_TOLEFT Or LVHT_TORIGHT Or _
               LVHT_ONITEMICON Or _
               LVHT_ONITEMLABEL Or _
   End With
   itemIndex = SendMessage(ListView1.hwnd, LVM_SUBITEMHITTEST, 0, hti)
   If itemIndex = -1 And _
      (hti.iSubItem = -1 Or _
       hti.iSubItem = 0) Then
      Set ListView1.SelectedItem = Nothing
   End If
End Sub

Private Sub ListView1_MouseUp(Button As Integer, _
                              Shift As Integer, _
                              x As Single, _
                              y As Single)
 'update label
   If Not ListView1.SelectedItem Is Nothing Then
      Label1.Caption = ListView1.SelectedItem.Text
      Label1.Caption = "(no selected index)"
   End If
End Sub

Private Function ListView_GetNextItem(hwnd As Long, _
                                      index As Long, _
                                      flags As Long) As Long

   ListView_GetNextItem = SendMessage(hwnd, _
                                      LVM_GETNEXTITEM, _
                                      index, _
                                      ByVal flags)

End Function

Private Function ListView_GetSelectedCount(hwnd As Long) As Long

   ListView_GetSelectedCount = SendMessage(hwnd, _
                                           LVM_GETSELECTEDCOUNT, _
                                           0&, _
                                           ByVal 0&)

End Function

Note that the code is split between the MouseDown and MouseUp events. This is due to the fact that in the MouseDown event, it is too early to retrieve the selected item information since it has not been set by the control. Similarly, the MouseDown code can not go into the MouseUp event because by that time its too late to clear the selected item.


PayPal Link
Make payments with PayPal - it's fast, free and secure!


Copyright 1996-2011 VBnet and Randy Birch. All Rights Reserved.
Terms of Use  |  Your Privacy


Hit Counter