A better way to gather multi-selected Visual Basic ListBox items
Conventional Visual Basic wisdom states that in order to gather the selected items from a multi-select ListBox, you should loop through all the items and test the Selected property. As with all loops, however, this can potentially bog down slower CPU注釋:s. As a mUCh faster and more elegant alternative, you can use the SendMessage() API function instead.
As you probably know, this function lets you send a message to one or more windows. The declaration statement conforms to the following syntax:
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
Since we want to gather the listbox注釋:s selected items, we注釋:ll send the LB_GETSELITEMS constant in the wMsg argument, which you declare like so:
Private Const LB_GETSELITEMS = &H191
In essence, the LB_GETSELITEMS message fills an array with the index numbers of all the selected items. As a result, you must pass two additional arguments with SendMessage(). The first argument should contain the maximum number of selected items. To retrieve this value, you can simply use the listbox注釋:s SelCount property. The second argument should hold the array variable you want to fill with index values. The following example shows how you might use this function:
Dim ItemIndexes() As Long, x As Integer, iNumItems As Integer
iNumItems = ThisBox.SelCount
If iNumItems Then
ReDim ItemIndexes(iNumItems - 1)
SendMessage ListBox1.hwnd, LB_GETSELITEMS, iNumItems, _
ItemIndexes(0)
End If
For x = 0 To iNumItems - 1
MsgBox ListBox1.List(ItemIndexes(x))
Next x
After being passed to the SendMessage function, iNumItems holds the total number of selected items, and the ItemIndexes array holds the selected item index values. Notice, that you must pass a pointer to the ItemIndexes array, and not the array itself. Thus, we passed ItemIndexes(0) into the SendMessage function, not ItemIndexes().
Conventional Visual Basic wisdom states that in order to gather the selected items from a multi-select ListBox, you should loop through all the items and test the Selected property. As with all loops, however, this can potentially bog down slower CPU注釋:s. As a mUCh faster and more elegant alternative, you can use the SendMessage() API function instead.
As you probably know, this function lets you send a message to one or more windows. The declaration statement conforms to the following syntax:
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
Since we want to gather the listbox注釋:s selected items, we注釋:ll send the LB_GETSELITEMS constant in the wMsg argument, which you declare like so:
Private Const LB_GETSELITEMS = &H191
In essence, the LB_GETSELITEMS message fills an array with the index numbers of all the selected items. As a result, you must pass two additional arguments with SendMessage(). The first argument should contain the maximum number of selected items. To retrieve this value, you can simply use the listbox注釋:s SelCount property. The second argument should hold the array variable you want to fill with index values. The following example shows how you might use this function:
Dim ItemIndexes() As Long, x As Integer, iNumItems As Integer
iNumItems = ThisBox.SelCount
If iNumItems Then
ReDim ItemIndexes(iNumItems - 1)
SendMessage ListBox1.hwnd, LB_GETSELITEMS, iNumItems, _
ItemIndexes(0)
End If
For x = 0 To iNumItems - 1
MsgBox ListBox1.List(ItemIndexes(x))
Next x
After being passed to the SendMessage function, iNumItems holds the total number of selected items, and the ItemIndexes array holds the selected item index values. Notice, that you must pass a pointer to the ItemIndexes array, and not the array itself. Thus, we passed ItemIndexes(0) into the SendMessage function, not ItemIndexes().

