|
Die Suche nach einem bestimmten Element in einer ListBox bzw.
einer ComboBox ließe sich in einer kleinen Hilfsfunktion etwa so
bewerkstelligen:
Function FindTextInList(ListBox As ListBox, GesuchterText _
As String) As Long
Dim l As Long
Dim nGesuchterText As String
nGesuchterText = LCase$(GesuchterText)
With ListBox
For l = 0 to .ListCount - 1
If LCase$(.List(l)) = nGesuchterText Then
FindTextInList = l
Exit For
End If
Next 'l
End With
End Function
Enthält die ListBox jedoch sehr viele Elemente, kostet eine
Suche auf diese Weise sehr viel Zeit. Falls Sie wissen sollten, dass
sich das gesuchte Element voraussichtlich sehr weit am Ende der
Liste befinden dürfte, könnten Sie natürlich die Suche auch vom
Ende her beginnen (For l = ListBox.ListCount - 1 To 0 Step
-1). Aber wie herum auch immer - irgendwie sieht das nicht
besonders elegant aus.
Die Lösung findet sich im Windows-API. Denn wie verschiedentlich
an anderen Stellen auch, "verschont" uns Visual Basic hier
wieder einmal vor einer essentiellen Funktionalität, die in
Windows-ListBoxen und -ComboBoxen eigentlich bereits eingebaut ist.
Da ListBoxen und ComboBoxen in Visual Basic von den
Windows-Originalen abgeleitet sind, steckt die Orginal-Funktion nach
wie vor darin, nur eben ohne Zugang in VB.
Sendet man einer ListBox bzw. einer ComboBox (im weiteren werde
ich nur noch von ListBoxen sprechen, da die Funktionen für
ComboBoxen identisch sind) über die API-Funktion SendMessage
eine Anfrage nach einem bestimmten Element, so bekommt man den
ListIndex zurückgeliefert, oder aber -1 (entsprechend den
Konstanten LB_ERR bzw. CB_ERR), wenn kein entsprechendes Element
gefunden werden konnte.
Die API-Funktion SendMessage kann jedoch auf vielfältige Weise
verwendet werden. Ihr können vor allem im Parameter lParam die
verschiedensten Datentypen übergeben werden. Damit Visual Basic
eindeutig weiß, dass hier ein String übergeben werden soll, nutzen
wir die Möglichkeit, eine Alias-Deklaration der Original-Funktion
zu erstellen und hierbei den Parameter lParam gleich als String zu
deklarieren:
Declare Function SendMessageStr Lib "user32" _
Alias "SendMessageA" ( _
ByVal hwnd As Long, _
ByVal wMsg As Long, _
ByVal wParam As Long, _
ByVal lParam As String _
) As Long
Damit ist auch Visual Basic in der Lage, mit einer Fehlermeldung
zu reagieren, sollten Sie irgendwann einmal versehentlich einen Wert
eines anderen Datentyps als String an dieser Stelle zu übergeben
versuchen.
Genau genommen bietet das API zwei Möglichkeiten, ein Element in
einer ListBox zu finden. Zum einen kann das erste Element gefunden
werden, das mit dem gesuchten insoweit übereinstimmt, als dass die
ersten Zeichen des gefundenen Elements mit den gesuchten
übereinstimmen - allerdings ohne Berücksichtigung der
Groß-/Kleinschreibung ( LB_FINDSTRING).
Bei der Suche etwa nach "haus" würde "Haushalt"
gefunden, wenn dieses Element als erstes in der Reihenfolge der
Elemente auftritt. Zum anderen kann aber auch nach einer exakten
Übereinstimmung gesucht werden ( LB_FINDSTRINGEXACT).
Weiterhin kann der ListIndex angegeben, werden, ab dem gesucht
werden soll. So kann als Start der ListIndex hinter dem jeweils
zuletzt gefundenen Element vorgegeben werden, damit weitere
übereinstimmende Elemente erreicht werden können.
Bei der einfachen Suche bietet das API praktischerweise auch an,
das gefundene Element auch gleich auszuwählen - bei der exakten
Suche müssen wir das leider von Hand nachträglich erledigen.
Die zwei folgenden Funktionen vereinfachen die Angelegenheit für
ListBoxen und für ComboBoxen, indem sie die notwendigen Aufrufe und
Parameter verpacken. Sie geben beim Aufruf dieser Funktionen nur
noch an, in welchem Steuerelement (ListBox bzw. ComboBox) gesucht
werden soll, welcher Text zu suchen ist, ab welchem ListIndex die
Suche losgehen soll, ob das gefundene Element gleich ausgewählt
werden soll und ob eine exakte Suche stattfinden soll. Bis auf die
Angabe des Steuerelements und des zu suchenden Textes sind alle
Parameter optional - Sie können sie weglassen. Geben Sie keinen
Start-Listindex an, beginnt die Suche beim ersten Element (mit dem
ListIndex 0).
Bei den Funktionen sind die Bedeutungen der Parameter noch einmal
als Kommentar zur Erläuterung eingefügt.
Private Declare Function SendMessageStr Lib "user32" _
Alias "SendMessageA" ( _
ByVal hwnd As Long, _
ByVal wMsg As Long, _
ByVal wParam As Long, _
ByVal lParam As String _
) As Long
Private Const LB_ERR = (-1)
Private Const CB_ERR = (-1)
Private Function ListFindText(iListBox As ListBox, _
iFindText As String, Optional ByVal iFromIndex As Long = -1, _
Optional ByVal iSelect As Boolean = False, _
Optional ByVal iExact As Boolean) As Long
'iFromIndex = TRUE für Suche ab Anfang, sonst ab ListIndex bis
' Ende und weiter von 0
'iSelect = TRUE für Auswahl aktuell setzen
'iExact = True, wenn iFindText exakt gefunden werden soll
'Rückgabewert = Index, wenn gefunden
'Rückgabewert = LB_ERR, wenn nicht gefunden
Dim nMsg As Long
Dim nIndex As Long
Const LB_FINDSTRING = &H18F
Const LB_SELECTSTRING = &H18C
Const LB_FINDSTRINGEXACT = &H1A2
Select Case iExact
Case False
Select Case iSelect
Case True
nMsg = LB_SELECTSTRING
Case False
nMsg = LB_FINDSTRING
End Select
ListFindText = SendMessageStr(iListBox.hwnd, nMsg, _
iFromIndex, iFindText)
Case True
With iListBox
nIndex = SendMessageStr(.hwnd, LB_FINDSTRINGEXACT, _
iFromIndex, iFindText)
If iSelect Then
.ListIndex = nIndex
End If
End With
ListFindText = nIndex
End Select
End Function
Private Function ComboFindText(iComboBox As ComboBox, _
iFindText As String, Optional ByVal iFromIndex As Long = -1, _
Optional ByVal iSelect As Boolean = False, _
Optional ByVal iExact As Boolean) As Long
'iFromIndex = TRUE für Suche ab Anfang, sonst ab ListIndex bis
' Ende und weiter von 0
'iSelect = TRUE für Auswahl aktuell setzen
'iExact = True, wenn iFindText exakt gefunden werden soll
'Rückgabewert = Index, wenn gefunden
'Rückgabewert = CB_ERR, wenn nicht gefunden
Dim nMsg As Long
Dim nIndex As Long
Const CB_SELECTSTRING = &H14D
Const CB_FINDSTRING = &H14C
Const CB_FINDSTRINGEXACT = &H158
Select Case iExact
Case False
Select Case iSelect
Case True
nMsg = CB_SELECTSTRING
Case False
nMsg = CB_FINDSTRING
End Select
ComboFindText = SendMessageStr(iComboBox.hwnd, nMsg, _
iFromIndex, iFindText)
Case True
With iComboBox
nIndex = SendMessageStr(.hwnd, CB_FINDSTRINGEXACT, _
iFromIndex, iFindText)
If iSelect Then
.ListIndex = nIndex
End If
End With
ComboFindText = nIndex
End Select
End Function
 |
Mit den Funktionen ListFindText und
ComboFindText finden Sie auf schnellstem Wege ein Element in
einer ListBox bzw. in einer ComboBox

|

|