Das Control selbst ist jedoch in der Lage deutlich mehr Daten zu verwalten.
Um diese Möglichkeit auch für VB-Anwender nutzbar zu machen,
muß man auf die API-Function SendMessage() zurückgreifen.
Das Demo-Programm, links ein ScreenShot zu sehen, zeigt eine Liste mit 200000 zufällig generierten KFT-Kennzeichen. Die Liste ist unsortiert, um auch die Suchfunktion zu demonstrieren. Ist Ihr Kennzeichen auch dabei? |
In der Windows-API sind eine Reihe Nachrichten definiert, die speziell
auf Listboxen ausgerichtet sind. Sie beginnen stets mit dem Prefix 'LB_'
für ListBox. Einige wichtige dieser ListBox-Nachrichten
möchte ich später vorstellen.
In einem Modul Namens modListBox.bas sind die wichtigsten Funktionen für das problemlose Einbinden und Verwenden in eigenen VB-Anwendungen verpackt.
Am Beispiel von KFZ-Kennzeichen, die in der Liste angezeigt werden,
wird demonstriert, wie diese Funktionen anzuwenden sind.
Der Code der Demo ist gut kommentiert und stellt über ToolTip-Texte
weitere Infos bereit.
Hinweis:
Die verbleibenden beiden Modul-Funktionen LBGetItemData
und LBSetItemData werden in der Demo nicht
demonstriert, wurden jedoch getestet und funktionieren.
Hier also alle definierten Funktionen des Moduls modListBox.bas
' ***********************************************
' *
Benutzer-Funktionen ListBox-Control *
' ***********************************************
'
Sucht String in ListBox, gibt Index zurück
' wenn Übereinstimmung
gefunden, sonst -1
' Der Eintrag
wird Markiert
Public Function LBSelectListItem(Obj
As ListBox, StartIndex As Long, FindString As String) As Long
LBSelectListItem
= SendMessage(Obj.hwnd, LB_SELECTSTRING, 0, ByVal FindString)
End Function
'
Sucht exakten String in ListBox, gibt Index bei
' Übereinstimmung
zurück, sonst -1
' Der Eintrag
wird nicht markiert
Public Function LBFindExactItem(Obj
As ListBox, StartIndex As Long, FindString As String) As Long
LBFindExactItem
= SendMessage(Obj.hwnd, LB_FINDSTRINGEXACT, StartIndex, ByVal FindString)
End Function
'
Sucht (nicht exakten) String in ListBox, gibt Index bei
' Übereinstimmung
zurück, sonst -1
' Der Eintrag
wird nicht Markiert
Public Function LBFindItem(Obj As
ListBox, StartIndex As Long, FindString As String) As Long
LBFindItem = SendMessage(Obj.hwnd,
LB_FINDSTRING, StartIndex, ByVal FindString)
End Function
'
ListIndex von ListBox ermitteln
' Gibt den aktuell
selektierten Index zurück
Public Function LBGetListIndex(Obj
As ListBox) As Long
LBGetListIndex
= SendMessage(Obj.hwnd, LB_GETCURSEL, 0, ByVal 0&)
End Function
'
ListIndex von ListBox setzen
' setzt den
ListIndex und markiert den Eintrag
' Ein Click
wird nicht ausgelöst!
Public Sub LBSetListIndex(Obj As ListBox,
NewIndex As Long)
Call SendMessage(Obj.hwnd,
LB_SETCURSEL, NewIndex, ByVal 0&)
End Sub
'
Anzahl List-Einträge ermitteln (ListCount)
Public Function LBGetListCount(Obj
As ListBox) As Long
LBGetListCount
= SendMessage(Obj.hwnd, LB_GETCOUNT, 0, ByVal 0&)
End Function
'
Liest den Text in einer ListBox aus mit dem
' angegebenen
Index aus und gibt diesen zurück
Public Function LBGetItemText(Obj
As ListBox, Index As Long) As String
Dim Buffer As String
Dim TextLen As
Long
TextLen = SendMessage(Obj.hwnd,
LB_GETTEXTLEN, Index, ByVal 0&)
If TextLen > 0
Then
Buffer = Space(TextLen)
Call SendMessage(Obj.hwnd, LB_GETTEXT, Index, ByVal Buffer)
End If
LBGetItemText =
Buffer
End Function
'
Löscht den Text aus der ListBox
' Gibt bei Erfolg
die Anzahl der verbleibenden
' Einträge
in der Liste zurück, bei Fehler -1
Public Function LBDeleteItem(Obj As
ListBox, Index As Long) As Long
LBDeleteItem =
SendMessage(Obj.hwnd, LB_DELETESTRING, Index, ByVal 0&)
End Function
'
Fügt ein Eintrag an die Position 'Index' ein
' Der eingefügte
Text wird nicht matkiert.
Public Sub LBInsertItem(Obj As ListBox,
Index As Long, Text As String)
Call SendMessage(Obj.hwnd,
LB_INSERTSTRING, Index, ByVal Text)
End Sub
'
Hängt ans Ende der Listbox einen Eintrag an.
' Liefert die
Position zurück, an der der text eingefügt wurde
' Der hinzugefügte
Text wird nicht markiert
Public Function LBAppendItem(Obj As
ListBox, Text As String) As Long
LBAppendItem =
SendMessage(Obj.hwnd, LB_ADDSTRING, 0, ByVal Text)
End Function
'
Ersetzt den Item-Text an der Position 'Index' mit 'NewText'
' Der Eintrag
wird markiert!
Public Sub LBSetItemText(Obj As ListBox,
Index As Long, NewText As String)
' zunächst
Eintrag löschen
If SendMessage(Obj.hwnd,
LB_DELETESTRING, Index, ByVal 0&) > 0 Then
' und neuen Eintrag an diese Position wieder einfügen
Call SendMessage(Obj.hwnd, LB_INSERTSTRING, Index, ByVal NewText)
' und noch selectieren
Call SendMessage(Obj.hwnd, LB_SETCURSEL, Index, ByVal 0)
End If
End Sub
'
Ermittelt den benutzerdefinierten Wert ItemData
' Der Wert wird
mit LBSetItemData() zugewiesen
Public Function LBGetItemData(Obj
As ListBox, Index As Long) As Long
LBGetItemData =
SendMessage(Obj.hwnd, LB_GETITEMDATA, Index, ByVal 0&)
End Function
'
setzt den benutzerdefinierten Wert ItemData
Public Sub LBSetItemData(Obj As ListBox,
Index As Long, ItemData As Long)
Call SendMessage(Obj.hwnd,
LB_SETITEMDATA, Index, ByVal ItemData)
End Sub
Gibt den Index des makierten Listen-Eintrags zurück. Ist kein Eintrag selektiert, erhält man -1 zurück. DNachricht entspricht in VB, wenn man so will, der Eigenschaft ListBox.ListIndex des ControlsLB_SETCURSEL
Diese Nachricht ist das Pendanz zu LB_GETCURSEL und setzt die Markierung auf den gewünschten Listen-Index. Das entspricht in VB der Eigenschaft ListBox.ListIndex=<indexwert>. Hier kann ein Index zwischen 0 und ind dem höchsten Index obergeben werden. Der höchste Index kann mit der Nachricht LB_GETCOUNT ermittelt werden. Im Gegensatz zu VB kann hier noch der Index-Wert -1 übergeben werden, das hat zur Folge, dass kein Eintrag markiert ist.LB_GETCOUNT
Diese Nachricht ermittelt den höchsten Index. In VB wäre das die Eigenschaft ListBox.ListCount. Ist die Liste Leer oder tritt ein Fehler auf, wird -1 zurückgegeben. LB_GETCOUNT wird zusammen mit LB_SETCURSEL verwendet, um sicherzustellen, dass kein ungültiger Index übergeben wird.LB_GETTEXT
Mit dieser Nachricht wird der Text des selektierten Listen-Eintrags ermittelt. Hierfür wird ein ausreichend grosser Buffer benötigt, in dem der Text abgelegt werden kann. Die Grösse des erforderlichen Buffers kann mit der Nachricht LB_GETTEXTLEN ermittelt werde.
In VB entspricht das der Methode Text=ListBox.List(...).
Diese Nachricht ermittelt die Länge des markierten Textes in Zeichen (Char). Bevor die Nachricht LB_GETTEXT verwendet wird, kann mit dieser Nachricht die erforderliche Buffer-Grösse ermittelt werden.LB_GETITEMDATA
In Visual Basic kann jeder einzelne Eintrag einen zusätzlichen 32-Bit-Wert erhalten. Die entsprechende Eigenschaft lautet <variable>=ListBox.ItemData(<index>). Mit dieser Nachricht kann der entsprechende Wert (ItemData) abgefragt werden. Mit LB_SETITEMDATA können frei wählbare 32-Bit-Werte zugewiesen werden.
Diese Nachricht weist einem Listen-Eintrag einen vom Benutzer frei wählbaren 32-Bit-Wert zu. Dadurch können zum jeweiligen Listeneintrag zusätzliche Informationen gespeichert werden. Beispielsweise in Index von einer Object-Collection oder ein Windows-Handle oder was auch immer. Dieser gesetzte ItemData-Wert kann mit der Nachricht LB_GETITEMDATA wieder ermittelt werden. In VB wäre dies die Eigenschaft ListBox.ItemDate(<Index>)=32-BitWert.LB_ADDSTRING
Diese Nachricht fügt einen neien Eintrag zur Liste hinzu. Ist die Liste unsortiert, wird der Text am Schluss angehängt, im anderen Fall wird er in die entsprechende Stelle eingefügt. Als Rückgabewert erhält man den Index oder -1 bei Fehler.
Die VB-Methode wäre ListBox.AddItem <Text>. Um einen Text an eine bestimmte Position einzufügen, muss die Nachricht LB_INSERTSTRING verwendet werden.
Diese Nachricht fügt einen Text an der angegebenen Index-Position ein. Im Gegensatz zu LB_ADDSTRING muß hier ein Index zwischen 0 und dem höchst zulässigen (siehe LB_GETCOUNT) angegeben werden. Als Rückgabe erhält man die Index-Position, an der der Text eingefügt wurde. Tritt ein Fehler auf, erhält man -1 zurück.
Diese Nachricht löscht den mit Index angegebenen Eintrag aus der Liste. Wurde der Eintrag erfolgreich gelöscht, erhält man als Rückgabewert den höchsten Index der verbleibenden Einträgen in der ListBox. Dies entspricht dem Wert, der bei LB_GETCOUNT ermittelt werden kann. Die entsprechende VB-Methode wäre ListBox.RemoveItem(<Index>).
Was man In Visual Vasic vergeblich sucht ist eine Möglichkeit,
einen Listen-Eintrag zu suchen und gebenenenfalls zu markieren. Hier bietet
die API 3 weitere ListBox-Nachrichten an, die für viele VB-Programmieren
von Interesse sein dürfte.
Diese Nachricht sucht in der ListBox den Text, der mit den selben Zeichen beginnt wie der Suchstring und liefert dieses Index zurück. Wird der Suchstring nicht gefunden erhält man -1. Der entsprechende Index wird hierbei nicht selektiert. Dies kann man jedoch nachholen und die Nachricht LB_SETCURSEL an das Control senden. Eine andere Möglichkeit wäre, die Nachricht LB_SELECTSTRING zu verwenden, die dann den entsprechenden Index gleich markiert.
Mit dieser Nachricht wird die ListBox nach einer exakten Übereinstimmung mit dem Suchstring gesucht. Wird ein Eintrag gefunden, wird der Index zurück geliefert. Ist die Suche erfolglos, erhält man -1 zurück. Der gefundene Text wird nicht selektiert.LB_SELECTSTRING
Diese Nachricht sucht in der ListBox genau wie LB_FINDSTRING den Text, der mit den seben Zeichen beginnt, wie der Suchstring. Im Gegensatz zu LB_FINDSTRING wird ein gefundener Index gleich markiert.Hinzufügen möchte ich noch, dass kein Maus-Click ausgelöst wird.