Die Programmierung des TreeView-Steuerelements haben wir bereits in vielen Beiträgen dokumentiert. Dort haben wir auch gezeigt, wie Sie Befehle für spezielle Elementtypen im TreeView in Kontextmenüs unterbringen, die beim Rechtsklick auf die jeweiligen Elemente angezeigt werden. Es gibt noch eine andere Möglichkeit, solche Befehle abhängig vom Elementtyp abzubilden: als Ribbon-Einträge. Wie das gelingt, zeigt der vorliegende Beitrag.
Beispieldatenbank
Im Beitrag TreeView mit Kontextmenü (www.access-im-unternehmen.de/1243) haben wir bereits Vorarbeiten für diesen Beitrag geleistet und ein funktionsfähiges TreeView-Steuerelement mit den Daten aus den beiden Tabellen tblKunden und tblProjekte gefüllt.
Dort haben wir beschrieben, wie Sie die Daten im TreeView mit Kontextmenü-Einträgen anpassen können. Im vorliegenden Beitrag wollen wir nun zeigen, wie Sie die entsprechenden Befehle in einem Ribbon unterbringen, das nur dann angezeigt wird, wenn der Benutzer auf ein Element eines bestimmten Typs klickt – also beispielsweise auf ein Kunden-Element oder ein Projekt-Element.
Das Ribbon soll dann die gleichen Befehle anzeigen, die auch das Kontextmenü zu dem entsprechenden Eintrag anzeigt und die gleichen Funktionen auslösen (siehe Bild 1). Wir beginnen mit der Beispieldatenbank TreeViewMitRibbon.accdb.
Bild 1: Die Befehle dieses Kontextmenüs wollen wir im Ribbon anzeigen, wenn der Benutzer einen der Einträge im TreeView anklickt.
Tabelle für die Ribbon-Definitionen anlegen
Wenn Sie Ribbons anzeigen möchten, benötigen Sie eine Tabelle namens USysRibbons, die nach einem bestimmten Schema aufgebaut ist und die Ribbon-Definitionen aufnimmt. Diese Tabelle enthält die folgenden drei Felder:
- ID: Primärschlüsselfeld der Tabelle mit Autowert-Funktion
- Ribbonname: Name des Ribbons
- RibbonXML: XML-Definition des Ribbons
Die Tabelle mit dem Namen USysRibbons wird aufgrund des Präfixes USys… als Systemobjekt erkannt und wird nur angezeigt, wenn Sie in den Navigationsoptionen von Access die Option Systemobjekte anzeigen aktivieren.
Diese Tabelle füllen wir dann gleich mit den gewünschten Ribbon-Definitionen (siehe Bild 2). Mit der ersten möchten wir erreichen, dass beim Anklicken eines der Kunde-Elemente im TreeView-Steuerelement ein kontextabhängiges Ribbon-Tab zum Ribbon hinzugefügt wird.
Bild 2: Die Tabelle USysRibbons mit den Ribbon-Definitionen
Deshalb deklarieren wir dieses wie in Listing 1. Das Element customUI enthält zwei Callback-Attribute:
<xml version="1.0">
<customUI xmlns="http://schemas.microsoft.com/office/2009/07/customui" onLoad="OnLoad_RibbonKunde"
loadImage="loadImage">
<ribbon>
<contextualTabs>
<tabSet idMso="TabSetFormReportExtensibility">
<tab id="tabKunde" label="Kunden">
<group id="grpKunde" label="Kunde">
<button image="user_delete_32" label="Kunde löschen" id="btnKundeLoeschen" onAction="onAction"
size="large"/>
<button image="folder2_plus_32" label="Neues Projekt" id="btnNeuesProjekt" onAction="onAction"
size="large"/>
<button onAction="onAction" size="large" image="edit_32" label="Umbenennen" id="btnKundeUmbenennen"/>
</group>
<group id="grpZwischenablage" label="Zwischenablage">
<button id="btnAusschneiden" image="cut_32" label="Ausschneiden" onAction="onAction" size="large"/>
<button id="btnKopieren" image="copy_32" label="Kopieren" onAction="onAction" size="large"/>
<button image="clipboard_paste_32" label="Einfügen" id="btnEinfuegen" onAction="onAction" size="large"/>
</group>
</tab>
</tabSet>
</contextualTabs>
</ribbon>
</customUI>
Listing 1: Definition des ersten Ribbons, das beim Anklicken eines Kunden angezeigt werden soll
- onLoad: Dieses Callback wird einmalig beim Laden der Ribbon-Definition ausgeführt. Die Callback-Funktion dient meist dazu, eine Variable des Typs IRibbonUI mit einem Verweis auf die Ribbon-Definition zu füllen, was auch hier der Fall ist.
- loadImage: Dieses Callback wird ausgelöst, wenn die Ribbon-Definition Elemente enthält, für die das Attribut image auf ein anzuzeigendes Bild eingestellt ist. Sie muss durch den Entwickler gefüllt werden, damit das Ribbon-Element das gewünschte Bild anzeigt.
Das ribbon-Element könnte man mit dem Attribut startFromScratch=”true” ausstatten, wenn man möchte, dass alle anderen und eingebauten Elemente des Ribbons beim Anzeigen ausgeblendet werden. Wir wollen dem Benutzer aber hier die Möglichkeit geben, dennoch die Befehle in den übrigen Ribbon-Tabs zu verwenden.
Um Ribbon-Tabs so anzuzeigen, dass sie nur im Kontext mit einem bestimmten Formular oder Element erscheinen, verwenden wir nicht die üblicherweise genutzte tabs-Auflistung, sondern das Element contextualTabs. Dieses geht meist einher mit dem untergeordneten Element tabSet, dem wir über das Attribut idMso mit dem Wert TabSetFormReportExtensibility die Information mitgeben, dass es gemeinsam mit Formularen oder Berichten angezeigt wird.
Danach folgt ein herkömmliches tab-Element mit der Beschriftung Kunden, darunter zwei group-Elemente. Das erste erhält die Beschriftung Kunde, das zweite die Beschriftung Zwischenablage. Die erste Gruppe enthält die drei Befehle Kunde löschen, Neues Projekt und Umbenennen. Für alle button-Elemente legen wir über das Attribut image den Namen des für diese Schaltfläche anzuzeigenden Bildes fest.
Außerdem stellen wir mit size=”large” ein, dass große Schaltflächen angezeigt werden sollen. Schließlich erhalten alle Schaltflächen das Attribut onAction mit dem Namen der Callback-Funktion, die beim Anklicken der Schaltfläche aufgerufen werden soll. Warum erhalten alle Schaltflächen den Aufruf der gleichen Callback-Funktion namens onAction Weil diese als Parameter den Namen des aufrufenden Elements erhält und wir in dieser Prozedur prüfen, von welchem Element der Aufruf kommt und die entsprechenden Befehle ausführen.
Dies soll ein Ribbon wie in Bild 3 ergeben. In den folgenden Abschnitten sehen wir uns an, wie wir das realisieren.
Bild 3: Das Ribbon zu den Kundeneinträgen im TreeView-Steuerelement
Ribbon-Verweis speichern
Wie oben erwähnt, soll beim Laden des Ribbons ein Verweis auf die Ribbon-Definition in einer Variablen gespeichert werden. Für diesen und anderen Ribbon-relevanten Code legen wir ein neues Modul namens mdlRibbons an. Diesem fügen wir als Erstes eine Variable für unser soeben definiertes Ribbon hinzu:
Public objRibbon_RibbonKunde As IRibbonUI
Dann können wir auch schon die Callback-Funktion implementieren, die wir für das Attribut onLoad des customUI-Elements der Ribbon-Definition angegeben haben. Diese sieht wie folgt aus:
Sub onLoad_RibbonKunde(ribbon As IRibbonUI) Set objRibbon_RibbonKunde = ribbon End Sub
Callback zum Zuweisen von Bildern
Danach legen wir die Callback-Prozedur an, die wir für das Callback-Attribut loadImage hinterlegt haben. Diese finden Sie in Listing 2. Die Prozedur erhält den für das Attribut image des jeweiligen Steuerelements angegebenen Namen des Bildes.
Public Sub loadImage(control, ByRef image) Dim lngID As Long On Error Resume Next lngID = Nz(DLookup("ID", "MSysResources", "Name = '" & control & "'"), 0) If Err.Number = 3078 Then MsgBox "Die Tabelle 'MSysResources' mit den Images für die Anzeige im Ribbon fehlt." & vbCrLf _ & "Fügen Sie die Images mit dem Ribbon-Admin hinzu", vbOKOnly + vbExclamation, _ "Tabelle MSysResources fehlt" Exit Sub End If On Error GoTo 0 If lngID = 0 Then MsgBox "Das Image '" & control & "' ist nicht in der Tabelle MSysResources vorhanden. " & vbCrLf _ & "Fügen Sie dieses über den Kontextmenüeintrag 'Benutzerdefiniertes Image hinzufügen' " & vbCrLf _ & "des image-Attributs des entsprechenden Ribbon-Steuerelements hinzu." Else Set image = PicFromSharedResource_Ribbon(CStr(control)) End If End Sub
Listing 2: Callback-Prozedur zum Laden der Bilder in die Ribbon-Schaltflächen
Sie wird für jedes Steuer-element, das dieses Attribut enthält, einmal aufgerufen. Die Prozedur greift auf Bilddateien zu, die in der Tabelle MSysResources hinterlegt sein müssen. Wie Sie diese dort hinterlegen, haben wir bereits im Beitrag TreeView mit Kontextmenü (www.access-im-unternehmen.de/1243) kurz beschrieben – in diesem Fall verwenden wir allerdings Bilder im Format 32 x 32 statt 16 x 16.
Die Funktion prüft mit einem Aufruf der DLookup-Funktion, ob sich in der Tabelle MSysResources ein Datensatz befindet, dessen Feld Name den Namen des Bildes aufweist und schreibt den gegebenenfalls gefundenen Primärschlüsselwert in die Variable lngID. Die Datensätze in der Tabelle MSysResources sehen etwa wie in Bild 4 aus.
Bild 4: Die Tabelle MSysResources mit den Bildern für das Ribbon
Hier kann es zu einem Fehler kommen, wenn die Tabelle MSysResources gar nicht vorhanden ist. Der Fehler hat die Nummer 3078. Tritt dieser Fehler auf, zeigt die Prozedur eine entsprechende Fehlermeldung an und die Prozedur wird beendet.
Anderenfalls prüft die Prozedur, ob lngID den Wert 0 hat. Das ist der Fall, falls die DLookup-Funktion keinen passenden Datensatz gefunden hat.
Auch in diesem Fall erscheint eine Meldung, die tunlichst während der Entwicklung der Anwendung auftreten sollte, damit der Entwickler die fehlenden Bilddateien zur Tabelle MSysResources hinzufügen kann.
Ist lngID jedoch nicht 0, dann wurde ein passender Datensatz gefunden. Dann übergeben wir den Namen des Steuerelements an die Funktion PicFromSharedResource_Ribbon, welche ein Objekt des Typs StdPicture zurückgibt. Dieses wird dann als Ergebnis der Callback-Funktion dem auslösenden Steuer-element zugewiesen.