In vielen Anwendungen finden Sie im Datei-Menü eine Auflistung der zuletzt geöffneten bzw. bearbeiteten Dokumente - eine so genannte "MRU"-Liste (Most Recently Used). Diese Liste hat entweder einen fest vorgegebenen Umfang (meistens 4 oder 6 Elemente), oder dieser kann vom Anwender individuell festgelegt werden. Sowohl der letzte Inhalt der Liste als auch die Umfangbegrenzung werden nach dem Beenden der Anwendung gesichert und beim nächsten Start der Anwendung wieder eingelesen. Die Funktionalität einer solchen MRU-Liste lässt sich recht einfach in einer Klasse unterbringen. Wir stellen Ihnen hier zwei Klassen vor - die Klasse clsMRU enthält die Grundfunktionalität, während die Klasse clsMRUMenu darüber hinaus ein Menü-Control-Array direkt verwaltet.
Die Basis beider Klassen bildet eine Collection, die die über die Add-Methode am Anfang der Liste eingefügten String-Elemente aufnimmt. Wird dabei die über die Eigenschaft Max festgelegte Anzahl überschritten, wird ein Element vom Ende der Collection entfernt. Über die für Collections üblichen Eigenschaften Count und Item können Sie die aktuelle Anzahl als auch einzelne Items auslesen, über die Methode Remove ein Element entfernen und über Clear die ganze Liste löschen. Über die Methode SelectItem können Sie ein einzelnes Element als aktuell gewähltes festlegen, das dazu an den Anfang der Liste verschoben wird. Sollte zufällig versucht werden, über die Add-Methode ein bereits vorhandenes Element erneut einzufügen, wird statt dessen intern die SelectItem-Methode aufgerufen und dieses Element somit an den Anfang der Liste verschoben.
Die Speicherung in der Windows-Registrierung unterhalb des Standard-Schlüssels "VB and VBA Program Settings" erfolgt über die Methode StoreSettings, der Sie mindestens einen Anwendungsnamen ("AppName") als spezifischen Schlüssel für Ihre Anwendung übergeben müssen. Optional können Sie noch einen Abschnittsnamen ("Section") übergeben, falls Ihnen die Vorgabe "MRU" nicht gefallen sollte, oder falls Sie mehrere solcher Listen in Ihrer Anwendung verwenden wollen. Das Auslesen nach dem Start erledigt die Methode ReadSettings mit den gleichlautenden Angaben von AppName und Section.
Schließlich können Sie noch über die Methode FillListCombo eine ListBox oder eine ComboBox mit dem Inhalt der Liste direkt füllen.
Der Code der Basis-Klasse clsMRU:
Private mMRUs As Collection
Private pMax As Long
Public Property Get Count() As Long
Count = mMRUs.Count
End Property
Public Property Get Item(KeyIndex As Variant) As String
On Error Resume Next
Item = mMRUs(KeyIndex)
End Property
Public Property Get Max() As Long
Max = pMax
End Property
Public Property Let Max(New_Max As Long)
If New_Max > 0 Then
pMax = New_Max
With mMRUs
Do While .Count > pMax
.Remove .Count
Loop
End With
Else
Err.Raise 5
End If
End Property
Public Sub Add(Item As String)
On Error Resume Next
With mMRUs
If .Count Then
.Add Item, Item, 1
If Err.Number = 457 Then
Me.SelectItem Item
Exit Sub
End If
Else
.Add Item, Item
End If
If .Count > pMax Then
.Remove .Count
End If
End With
End Sub
Public Sub Clear()
Set mMRUs = New Collection
End Sub
Public Sub FillListCombo(List As Control)
Dim l As Long
With List
.Clear
For l = 1 To mMRUs.Count
.AddItem mMRUs(l)
Next 'l
End With
End Sub
Public Sub ReadSettings(AppName As String, _
Optional Section As String = "MRU")
Dim nItems As Variant
Dim l As Long
Set mMRUs = New Collection
nItems = GetAllSettings(AppName, Section)
If IsArray(nItems) Then
pMax = CLng(nItems(0, 1))
With mMRUs
For l = LBound(nItems) + 1 To UBound(nItems)
.Add CStr(nItems(l, 1)), CStr(nItems(l, 1))
Next 'l
End With
End If
End Sub
Public Sub Remove(KeyIndex As Variant)
On Error Resume Next
mMRUs.Remove KeyIndex
End Sub
Public Sub StoreSettings(AppName As String, _
Optional Section As String = "MRU")
Dim l As Long
On Error Resume Next
DeleteSetting AppName, Section
On Error GoTo 0
SaveSetting AppName, Section, "Max", pMax
For l = 1 To mMRUs.Count
SaveSetting AppName, Section, Section & l, mMRUs(l)
Next 'l
End Sub
Public Sub SelectItem(KeyIndex)
Dim nItem As String
With mMRUs
If .Count > 1 Then
nItem = mMRUs(KeyIndex)
.Remove KeyIndex
.Add nItem, nItem, 1
End If
End With
End Sub
Public Function NewEnum() As IUnknown
Set NewEnum = mMRUs.[_NewEnum]
End Function
Private Sub Class_Initialize()
pMax = 4
Set mMRUs = New Collection
End Sub
Die Klasse clsMRUMenu verwaltet darüber hinaus direkt ein Menü, das als Control-Array mit dem Index 0 vorbereitet sein muss und mit einem Aufruf der Init-Methode an die Klasse übergeben wird. Wird dazu mindestens der optionale Parameter AppName angegeben, wird intern auch die Methode ReadSettings zum Einlesen einer gespeicherten Liste aus der Registrierung aufgerufen.
Das Menü-Steuerelement mit dem Index 0 wird immer als Trennstrich dargestellt und ist nur sichtbar, wenn die Liste Elemente enthält. Anderenfalls wird dieser Trennstrich verborgen. Zur Verwaltung des Menüs wird intern die Methode Refresh nach jeder relevanten Änderung aufgerufen, die für die benötigte Anzahl der Elemente im Control-Array sorgt, deren Caption-Eigenschaft ein MRU-Element zuweist und sie anzeigt, oder überzählige Control-Array-Elemente entfernt.
Public Sub Init(MenuArray As Object, Optional AppName As String, _
Optional Section As String = "MRU")
Set pMenuArray = MenuArray
With pMenuArray(0)
.Caption = "-"
If StrPtr(AppName) Then
Me.ReadSettings AppName, Section
Else
.Visible = 0
End If
End With
End Sub
Public Sub Refresh()
Dim l As Long
If Not (pMenuArray Is Nothing) Then
With mMRUs
pMenuArray(0).Visible = CBool(.Count)
On Error Resume Next
For l = 1 To .Count
Load pMenuArray(l)
With pMenuArray(l)
.Caption = mMRUs(l)
.Visible = True
End With
Next 'l
End With
With pMenuArray
Do While .UBound > mMRUs.Count
Unload pMenuArray(.UBound)
Loop
End With
End If
End Sub
Die vollständige Klasse clsMRUMenu finden Sie im Beispiel-Projekt (Download) zu diesem Artikel - sie unterscheidet sich im wesentlichen nur durch die internen Aufrufe der Refresh-Methode an den Stellen, an denen die Liste sich ändert.
|