|
Eine ComboBox kann recht praktisch sein, auch wenn es von
vornherein noch nichts auszuwählen geben sollte. Sie kann ja
nämlich auch die vom Anwender zuletzt eingegebenen und verwendeten
Eingaben speichern und als Auswahlliste zur Verfügung stellen, wie
Sie es beispielsweise im Ausführen-Dialog von Windows sehen. Und
wenn Sie wollen, können die gespeicherten Einträge auch die
Laufzeit einer Anwendung überdauern und nach dem nächsten Start
wieder zur Verfügung stehen.
Über die Funktion ComboAddItemUnique können Sie diese
Speicherung automatisieren. Sie übergeben Ihr zunächst die
betreffende ComboBox. Fehlt im folgenden optionalen Parameter Item
das aufzunehmende Element, wird automatisch der Inhalt der
Text-Eigenschaft der ComboBox verwendet. Das neue Element wird
jedoch nur eingefügt, wenn es nicht bereits in der Liste enthalten
sein sollte. Die Prüfung dazu erfolgt über die Nachricht
CB_FINDSTRINGEXACT und eine Deklarations-Variante der API-Funktion SendMessage
(siehe "Wer
suchet - der findet").
Setzen Sie den optionalen Parameter ToTop auf True, und
vorausgesetzt, die Sorted-Eigenschaft der ComboBox ist False, wird
das bereits vorgefundene oder das neu einzufügende Element am
Anfang der Liste eingefügt, anderenfalls am Ende bzw. an der der
Sortierung entsprechenden Stelle. Über den weiteren optionalen
Parameter AutoSelect legen Sie fest (Voreinstellung gleich True), ob
der ListIndex auch gleich auf das neue Element gesetzt werden soll.
Im letzten optionalen Parameter MaxItems können Sie schließlich
noch die maximale Anzahl der Elemente festlegen, die die ComboBox
aufnehmen soll. Legen Sie diese Obergrenze fest und wird Sie
überschritten, falls das neue Element noch nicht in der Liste
enthalten ist und daher eingefügt wird, wird das älteste Element
vorher entfernt. Hatten Sie ToTop auf True gesetzt, wird das Element
vom Ende der Liste entfernt, anderenfalls vom Anfang. Bei einer
sortierten Liste hat der Parameter keine Wirkung, da das Nachhalten
des ältesten Elements nur verhältnismäßig aufwändig zu
realisieren wäre.
Der Rückgabewert der Funktion enthält den ListIndex des neu
eingefügten bzw. des bereits vorgefundenen (und gegebenenfalls an
den Listenanfang verschobenen Elements).
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
Public Function ComboAddItemUnique(Combo As ComboBox, _
Optional Item As String, Optional ByVal ToTop As Boolean, _
Optional ByVal AutoSelect As Boolean = True, _
Optional ByVal MaxItems As Long) As Long
Dim nIndex As Long
Dim nExists As Boolean
Dim nItem As String
Dim nItemData As Long
Const CB_ERR = (-1)
Const CB_FINDSTRINGEXACT = &H158
With Combo
If StrPtr(Item) = 0 Then
nItem = .Text
Else
nItem = Item
End If
nIndex = SendMessageStr(.hwnd, CB_FINDSTRINGEXACT, -1, nItem)
If CBool(nIndex <> CB_ERR) Then
If ToTop And Not .Sorted Then
nItem = .List(nIndex)
nItemData = .ItemData(nIndex)
.RemoveItem nIndex
nIndex = 0
Else
nExists = True
End If
End If
If Not nExists Then
If Not .Sorted Then
If MaxItems > 0 Then
If .ListCount = MaxItems Then
If ToTop Then
.RemoveItem .ListCount - 1
Else
.RemoveItem 0
End If
End If
End If
If ToTop Then
.AddItem nItem, 0
.ItemData(.NewIndex) = nItemData
nExists = True
End If
End If
If Not nExists Then
.AddItem nItem
End If
nIndex = .NewIndex
End If
If AutoSelect Then
.ListIndex = nIndex
End If
ComboAddItemUnique = nIndex
End With
End Function
Das gleiche Prinzip können Sie auch bei einer ListBox anwenden.
Der Unterschied der Funktion ListAddItemUnique liegt lediglich
darin, dass der Item-Parameter nicht optional ist. Sie müssen hier
in jedem Fall ein Element übergeben, da eine ListBox ja kein
eigenes Eingabefeld hat.
Mit den beiden Prozeduren SaveSettingComboItems und
GetSettingComboItems (bzw. SaveSettingListItems und
GetSettingListItems) können Sie die Liste (z.B. beim
Programmende im Form_Unload-Ereignis) in der Windows-Registrierung
ablegen (Schlüssel "HKEY_CURRENT_USER\Software\VB and
VBA Program Settings") und von dort wieder einlesen (z.B.
beim nächsten Programmstart im Form_Load-Ereignis). Beachten Sie
dabei, dass Sie unter Section einen eigenen, separaten Namen
hierfür angeben müssen, da der Abschnitt vor jeder Speicherung
komplett gelöscht wird.
Setzen Sie bei SaveSettingComboItems den letzten, optionalen
Parameter ClearOnly auf True, wird lediglich der Abschnitt
gelöscht. Der Rückgabewert der Funktion GetSettingComboItems ist
True, wenn der Abschnitt vorhanden war und eingelesen werden konnte.
Public Sub SaveSettingComboItems(ComboBox As ComboBox, _
AppName As String, Section As String, Key As String, _
Optional ByVal ClearOnly As Boolean)
Dim l As Long
Dim nFormat As String
With ComboBox
On Error Resume Next
DeleteSetting AppName, Section
On Error GoTo 0
If Not ClearOnly Then
SaveSetting AppName, Section, "Items" & Key, 1
nFormat = String$(Len(CStr(.ListCount)), "0")
For l = 0 To .ListCount - 1
SaveSetting _
AppName, Section, Key & Format$(l, nFormat), .List(l)
Next 'l
End If
End With
End Sub
Public Function GetSettingComboItems(ComboBox As ComboBox, _
AppName As String, Section As String, Key As String) As Boolean
Dim nSettings As Variant
Dim l As Long
If CBool(GetSetting(AppName, Section, "Items" & Key, 0)) Then
GetSettingComboItems = True
With ComboBox
nSettings = GetAllSettings(AppName, Section)
For l = LBound(nSettings, 1) + 1 To UBound(nSettings, 1)
.AddItem nSettings(l, 1)
Next 'i
End With
End If
End Function
|