{"id":55000501,"date":"2026-04-01T00:00:00","date_gmt":"2026-05-16T15:38:04","guid":{"rendered":"http:\/\/access-im-unternehmen.aix-dev.de\/aiu\/?p=501"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-30T00:00:00","slug":"Eigene_Icons_in_Ribbon_und_Backstage_anzeigen","status":"publish","type":"post","link":"https:\/\/vbentwickler.de\/Eigene_Icons_in_Ribbon_und_Backstage_anzeigen\/","title":{"rendered":"Eigene Icons in Ribbon und Backstage anzeigen"},"content":{"rendered":"<p><img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/vg08.met.vgwort.de\/na\/671d94c496f2423e86ffbe0fafbdeb61\" width=\"1\" height=\"1\" alt=\"\"><b>Durch Anpassung des Ribbons oder des Backstage-Bereichs kann man seinen Anwendungen praktische Elemente zum Aufrufen von Funktionen, Formularen oder Berichten hinzuf&uuml;gen. Noch individueller werden benutzerdefinierte Ribbons und der Backstage-Bereich, wenn man den Steuerelementen auch noch eigene Icons hinzuf&uuml;gt. Das ist jedoch mit Bordmitteln nicht so einfach m&ouml;glich. Fr&uuml;her hat man diese Aufgabe unter Verwendung zahlreicher API-Funktionen aus der GDI-Bibliothek erledigt. Mittlerweile haben wir wesentlich einfachere Routinen daf&uuml;r entwickelt. In diesem Artikel stellen wir diese vor und zeigen, wie Du Ribbon- und Backstage-Steuerelemente einfach mit solchen Icons ausstatten kannst.<\/b><\/p>\n<h2>Voraussetzung<\/h2>\n<p>Wie immer, wenn wir das Ribbon f&uuml;r eine Datenbank-Anwendung individuell anpassen wollen, ben&ouml;tigen wir die Ribbon-Definition selbst. Diese speichern wir in der Tabelle <b>USysRibbons <\/b>(siehe Bild 1).<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2026_02\/pic_501_001.png\" alt=\"Ribbon-Definition in der Tabelle USysRibbons\" width=\"649,627\" height=\"306,7904\" \/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 1: Ribbon-Definition in der Tabelle USysRibbons<\/span><\/b><\/p>\n<h2>Bilder im Ribbon<\/h2>\n<p>Der erste Bereich, den wir mit eigenen Bildern ausstatten wollen, ist ein <b>tab<\/b>-Element im Ribbon. Daf&uuml;r haben wir ein neues Tab namens Projektverwaltung angelegt, das im Endergebnis wie in Bild 2 aussieht.<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2026_02\/pic_501_003.png\" alt=\"Ribbon-Steuerelemente mit Bildern\" width=\"649,627\" height=\"254,5321\" \/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 2: Ribbon-Steuerelemente mit Bildern<\/span><\/b><\/p>\n<p>Den XML-Code f&uuml;r diesen Bereich sehen wir in Listing 1. Hier haben wir an einigen Stellen f&uuml;r das Attribut <b>image<\/b> den Namen des jeweiligen Bildes angegeben.<\/p>\n<pre>Bild 1&lt;customUI xmlns=\"http:\/\/schemas.microsoft.com\/office\/2009\/07\/customui\" onLoad=\"onLoad\" loadImage=\"loadImage\"&gt;\r\n  &lt;ribbon&gt;\r\n    &lt;tabs&gt;\r\n      &lt;tab id=\"tabProjekt\" label=\"Projektverwaltung\" insertAfterMso=\"TabHome\"&gt;\r\n        &lt;group id=\"grpDokumente\" label=\"Dokumente\" imageMso=\"FileSave\"&gt;\r\n          &lt;button id=\"btnNeuesProjekt\" label=\"Neues Projekt\" image=\"cubes\" size=\"large\" onAction=\"onAction\"\/&gt;\r\n          &lt;button id=\"btnProjektOeffnen\" label=\"Projekt &ouml;ffnen\" image=\"folder_cubes\" size=\"large\" onAction=\"onAction\"\/&gt;\r\n          &lt;separator id=\"sep1\"\/&gt;\r\n          &lt;button id=\"btnSpeichern\" label=\"Speichern\" image=\"floppy_disk\" size=\"normal\" onAction=\"onAction\"\/&gt;\r\n          &lt;button id=\"btnExportieren\" label=\"Exportieren\" image=\"export\" size=\"normal\" onAction=\"onAction\"\/&gt;\r\n          &lt;button id=\"btnDrucken\" label=\"Drucken\" image=\"printer\" size=\"normal\" onAction=\"onAction\"\/&gt;\r\n        &lt;\/group&gt;\r\n        &lt;group id=\"grpTeam\" label=\"Team\"&gt;\r\n          &lt;button id=\"btnMitgliedHinzu\" label=\"Mitglied hinzuf&uuml;gen\" image=\"user\" size=\"large\" onAction=\"onAction\"\/&gt;\r\n          &lt;button id=\"btnNachricht\" label=\"Nachricht senden\" image=\"mail\" size=\"large\" onAction=\"onAction\"\/&gt;\r\n          &lt;separator id=\"sep2\"\/&gt;\r\n          &lt;button id=\"btnAufgaben\" label=\"Aufgaben\" image=\"checkbox\" size=\"normal\" onAction=\"onAction\"\/&gt;\r\n          &lt;button id=\"btnKalender\" label=\"Kalender\" image=\"calendar\" size=\"normal\" onAction=\"onAction\"\/&gt;\r\n        &lt;\/group&gt;\r\n        &lt;group id=\"grpBerichte\" label=\"Berichte\"&gt;\r\n          &lt;button id=\"btnStatusbericht\" label=\"Statusbericht\" image=\"clipboard_paste\" size=\"large\" onAction=\"onAction\"\/&gt;\r\n          &lt;splitButton id=\"sbZeiterfassung\" size=\"large\"&gt;\r\n            &lt;button id=\"btnZeiterfassung\" label=\"Zeiterfassung\" image=\"timer\" onAction=\"onAction\"\/&gt;\r\n            &lt;menu id=\"mnuZeiterfassung\" label=\"Zeiterfassung\"&gt;\r\n              &lt;button id=\"btnZeitStarten\" label=\"Starten\" image=\"media_play\" onAction=\"onAction\"\/&gt;\r\n              &lt;button id=\"btnZeitStoppen\" label=\"Stoppen\" image=\"media_stop\" onAction=\"onAction\"\/&gt;\r\n              &lt;menuSeparator id=\"msep1\"\/&gt;\r\n              &lt;button id=\"btnZeitUebersicht\" label=\"&Uuml;bersicht\" image=\"window_time\" onAction=\"onAction\"\/&gt;\r\n            &lt;\/menu&gt;\r\n          &lt;\/splitButton&gt;\r\n        &lt;\/group&gt;\r\n      &lt;\/tab&gt;\r\n    &lt;\/tabs&gt;\r\n  &lt;\/ribbon&gt;\r\n  ...<\/pre>\n<p><b><span style=\"color:darkgrey;\">Listing 1: Erster Teil der Ribbon-Definition<\/span><\/b><\/p>\n<h2>Bilder im Backstage-Bereich<\/h2>\n<p>Au&szlig;erdem wollen wir den Backstage-Bereich an einigen Stellen mit eigenen Bildern versehen. Dazu haben wir der Ribbon-Definition im Bereich <b>backstage<\/b> die Elemente wie in Listing 2 hinzugef&uuml;gt.<\/p>\n<pre>...\r\n&lt;backstage&gt;\r\n    &lt;tab id=\"tabProjektInfo\" label=\"Projektinfo\" insertAfterMso=\"TabInfo\" title=\"Projektverwaltung\"&gt;\r\n      &lt;firstColumn&gt;\r\n        &lt;group id=\"grpProjektdaten\" label=\"Projektdaten\"&gt;\r\n          &lt;primaryItem&gt;\r\n            &lt;button id=\"btnProjektSpeichern\" label=\"Projekt speichern\" _\r\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  image=\"clipboard_paste\" onAction=\"onAction\"\/&gt;\r\n          &lt;\/primaryItem&gt;\r\n          &lt;topItems&gt;\r\n            ...\r\n          &lt;\/topItems&gt;\r\n          &lt;bottomItems&gt;\r\n            &lt;hyperlink id=\"lnkDoku\" label=\"Projektdokumentation\" image=\"upload\" _\r\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  target=\"https:\/\/www.example.com\"\/&gt;\r\n          &lt;\/bottomItems&gt;\r\n        &lt;\/group&gt;\r\n      &lt;\/firstColumn&gt;\r\n      ...\r\n    &lt;\/tab&gt;\r\n  &lt;\/backstage&gt;\r\n&lt;\/customUI&gt;<\/pre>\n<p><b><span style=\"color:darkgrey;\">Listing 2: Zweiter Teil der Ribbon-Definition, hier f&uuml;r den Backstage-Bereich<\/span><\/b><\/p>\n<p>Diese Erweiterungen spiegeln sich im Backstage-Bereich in einem neuen <b>tab<\/b>-Element wieder, das nach dem Anklicken den Bereich aus Bild 3 liefert.<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2026_02\/pic_501_002.png\" alt=\"Backstage-Bereich mit einigen Bildern\" width=\"699,627\" height=\"300,3275\" \/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 3: Backstage-Bereich mit einigen Bildern<\/span><\/b><\/p>\n<h2>Verschieden Bildgr&ouml;&szlig;en<\/h2>\n<p>Wir k&ouml;nnen in den meisten Steuerelementen im Ribbon zwei Bildgr&ouml;&szlig;en verwenden.<\/p>\n<p>Wenn wir die Eigenschaft <b>size <\/b>f&uuml;r das Element auf <b>normal <\/b>einstellen oder diese weglassen, werden die Bilder mit 16 x 16 Pixeln angezeigt. Geben wir large an, erscheinen die Bilder mit 32 x 32 Pixeln. Optimalerweise liegen die Bilddateien in der passenden Gr&ouml;&szlig;e vor, also 16 x 16 Pixel f&uuml;r kleine und 32 x 32 Pixel f&uuml;r gro&szlig;e Bilder.<\/p>\n<p>Die Bilddateien sollten au&szlig;erdem in einem Format vorliegen, das Transparenz unterst&uuml;tzt. Optimal sind <b>.png<\/b>-Bilder geeignet, aber es funktioniert auch mit <b>.ico<\/b>&#8211; und <b>.bmp<\/b>-Dateien.<\/p>\n<h2>Weitere Schritte<\/h2>\n<p>Mit der Angabe von Bildnamen f&uuml;r die <b>image<\/b>-Elemente haben wir bereits den ersten Teil geschafft &#8211; wir haben festgelegt, welches Bild f&uuml;r welches Steuerelement angezeigt werden soll. Es fehlen noch zwei weitere Schritte:<\/p>\n<ul>\n<li>Wir m&uuml;ssen f&uuml;r das Element <b>customUI <\/b>im Attribut <b>loadImage <\/b>angeben, welche VBA-Prozedur daf&uuml;r sorgt, dass die im <b>image<\/b>-Attribut angegebenen Bilddateien geladen werden.<\/li>\n<li>Au&szlig;erdem m&uuml;ssen wir die Bilddateien noch verf&uuml;gbar machen. Diese hinterlegt man dazu am einfachsten in der Tabelle <b>MSysResources<\/b>, in der auch die Icons f&uuml;r Schaltfl&auml;chen oder Bild-Steuerelemente in Formularen hinterlegt werden.<\/li>\n<\/ul>\n<h2>Bilder in der Tabelle MSysResources hinterlegen<\/h2>\n<p>Zum Hinterlegen der Bilder gibt es eine einfache M&ouml;glichkeit &uuml;ber die Benutzeroberfl&auml;che, die wir ein wenig zweckentfremden.<\/p>\n<p>Dazu &ouml;ffnen wir ein Formular in der Entwurfsansicht und w&auml;hlen im Ribbon den Befehl <b>Formularentwurf|Steuerelemente|Bild einf&uuml;gen <\/b>aus und klicken unten auf <b>Durchsuchen<\/b>.<\/p>\n<p>Dies &ouml;ffnet einen Dateiauswahl-Dialog, mit dem wir die Icons einzeln zur Tabelle <b>MSysResources <\/b>hinzuf&uuml;gen k&ouml;nnen. Wir brauchen das Bild anschlie&szlig;end gar nicht zum Formularentwurf hinzuzuf&uuml;gen, es wird automatisch in der Tabelle <b>MSysResources <\/b>gespeichert.<\/p>\n<p>Das erkennen wir auch daran, dass alle hinzugef&uuml;gten Bilder anschlie&szlig;end nach einem Klick auf <b>Bild hinzuf&uuml;gen<\/b> in der Liste erscheinen (siehe Bild 4).<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2026_02\/pic_501_004.png\" alt=\"Bilder in der Tabelle MSysResources\" width=\"599,6265\" height=\"486,958\" \/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 4: Bilder in der Tabelle MSysResources<\/span><\/b><\/p>\n<h2>Callback-Funktion zum Einlesen der Bilder<\/h2>\n<p>Die Callback-Funktion, die wir im Attribut <b>loadImages <\/b>des Elements <b>customUI <\/b>hinterlegt haben, enth&auml;lt nur eine Anweisung:<\/p>\n<pre><span style=\"color:blue;\">Public Sub <\/span>loadImage(control, ByRef image)\r\n    <span style=\"color:blue;\">Set<\/span> image = amvGetImageFromResourcesByName(control)\r\n<span style=\"color:blue;\">End Sub<\/span><\/pre>\n<p>Die hier angegebene Funktion erwartet den Namen der Bilddatei, so wie er in der Tabelle <b>MSysResources <\/b>im Feld <b>Name <\/b>gespeichert ist, also ohne Dateiendung.<\/p>\n<h2>Funktion zum Lesen von Bildern aus MSysResources<\/h2>\n<p>Die Funktion <b>amvGetImageFromResourcesByName<\/b> liest ein Bild aus der Access-Systemtabelle <b>MSysResources<\/b> und gibt es als <b>StdPicture<\/b>-Objekt zur&uuml;ck, das Access direkt als Icon in Ribbon- und Backstage-Steuerelementen verwenden kann (siehe Listing 3).<\/p>\n<pre><span style=\"color:blue;\">Public <\/span>Declare PtrSafe Sub amvCopyMemory Lib \"Kernel32.dll\" Alias \"RtlMoveMemory\" (Destination<span style=\"color:blue;\"> As <\/span>Any, _\r\n    Source<span style=\"color:blue;\"> As <\/span>Any, ByVal Length<span style=\"color:blue;\"> As Long<\/span>Ptr)\r\n<span style=\"color:blue;\">Public Function <\/span>amvGetImageFromResourcesByName(strName<span style=\"color:blue;\"> As Variant<\/span>)<span style=\"color:blue;\"> As <\/span>StdPicture\r\n    <span style=\"color:blue;\">Dim <\/span>rst<span style=\"color:blue;\"> As <\/span>DAO.Recordset\r\n    <span style=\"color:blue;\">Dim <\/span>bytData()<span style=\"color:blue;\"> As Byte<\/span>\r\n    <span style=\"color:blue;\">Dim <\/span>bytRaw()<span style=\"color:blue;\"> As Byte<\/span>\r\n    <span style=\"color:blue;\">Dim <\/span>lngOffset<span style=\"color:blue;\"> As Long<\/span>\r\n    <span style=\"color:blue;\">Set<\/span> rst = CurrentDb.OpenRecordset( _\r\n        \"SELECT Data.FileData FROM MSysResources WHERE Name = '\" & strName & \"'\", dbOpenSnapshot)\r\n    <span style=\"color:blue;\">If <\/span>rst.EOF<span style=\"color:blue;\"> Then<\/span> <span style=\"color:blue;\">Exit Function<\/span>\r\n    bytRaw = rst.Fields(0)\r\n    lngOffset = bytRaw(0)\r\n    ReDim bytData(<span style=\"color:blue;\">UBound<\/span>(bytRaw) - lngOffset)\r\n    amvCopyMemory bytData(0), bytRaw(lngOffset), <span style=\"color:blue;\">UBound<\/span>(bytData)\r\n    <span style=\"color:blue;\">With<\/span> CreateObject(\"WIA.Vector\")\r\n        .BinaryData = bytData\r\n        <span style=\"color:blue;\">Set<\/span> amvGetImageFromResourcesByName = .Picture\r\n    End <span style=\"color:blue;\">With<\/span>\r\n<span style=\"color:blue;\">End Function<\/span><\/pre>\n<p><b><span style=\"color:darkgrey;\">Listing 3: Die Funktion amvGetImageFromResourcesByName<\/span><\/b><\/p>\n<p>Der Parameter <b>strName<\/b> empf&auml;ngt den Namen des Bildes, wie er in <b>MSysResources<\/b> hinterlegt ist. Dieser Name entspricht dem Wert des <b>image<\/b>-Attributs im XML &#8211; ruft Access also den <b>loadImage<\/b>-Callback auf, &uuml;bergibt es genau diesen String.<\/p>\n<p>Im ersten Schritt &ouml;ffnet die Funktion ein Recordset auf die Tabelle <b>MSysResources<\/b>. Das Feld <b>Data<\/b> ist ein Anlagefeld, das die eigentliche Bilddatei enth&auml;lt. &Uuml;ber die Notation <b>Data.FileData<\/b> greifen wir direkt auf die Bin&auml;rdaten der Anlage zu, ohne den Umweg &uuml;ber ein separates Recordset f&uuml;r das Anlagefeld nehmen zu m&uuml;ssen.<\/p>\n<p>Liefert die Abfrage keinen Treffer, verl&auml;sst die Funktion den Ablauf &uuml;ber <b>Exit Function<\/b> und gibt implizit <b>Nothing<\/b> zur&uuml;ck. Access zeigt das betreffende Steuerelement dann einfach ohne Icon an.<\/p>\n<p>Wurde ein Datensatz gefunden, lesen wir die Bin&auml;rdaten in ein Byte-Array <b>bytRaw<\/b> ein. Dieses Array enth&auml;lt allerdings nicht nur die reine Bilddatei: Access stellt den eigentlichen Daten einen Header voran. Die L&auml;nge dieses Headers steht im ersten Byte des Arrays. Mit diesem Offset kopieren wir &uuml;ber die API-Funktion <b>amvCopyMemory<\/b> nur die eigentlichen Bilddaten in ein zweites Array <b>bytData<\/b>. Diese API-Funktion deklarieren wir in dem Modul, in dem sich auch die Funktion <b>amvGetImageFromResourcesByName<\/b> befindet.<\/p>\n<p>Im letzten Schritt erzeugen wir &uuml;ber <b>CreateObject(&#8220;WIA.Vector&#8221;)<\/b> ein WIA-Objekt (<b>Windows Image Acquisition<\/b>). Dessen Eigenschaft <b>BinaryData <\/b>nimmt das Byte-Array entgegen, und die Eigenschaft <b>Picture<\/b> liefert daraus ein <b>StdPicture<\/b>-Objekt, das wir als Funktionsergebnis zur&uuml;ckgeben.<\/p>\n<p>Die Funktion kommt ohne Fehlerbehandlung mit <b>On Error<\/b> aus, da kein Fall auftreten kann, in dem ein stilles Verschlucken von Fehlern sinnvoll w&auml;re.<\/p>\n<p>Wird ein ung&uuml;ltiger Name &uuml;bergeben, gibt die Funktion <b>Nothing<\/b> zur&uuml;ck. Ist die Bilddatei besch&auml;digt, erzeugt VBA einen regul&auml;ren Laufzeitfehler, den der aufrufende Code behandeln kann.<\/p>\n<p>Damit landen alle gew&uuml;nschten Bilder in den jeweiligen Steuerelementen.<\/p>\n<h2>Downloads zu diesem Beitrag<\/h2>\n<p>Enthaltene Beispieldateien:<\/p>\n<p>IconsInRibbonKontextmenueFormularUndTreeView.accdb<\/p>\n<p><a href=\"..\/fileadmin\/beispiele\/F497342D-3AFF-49FD-B03A-F2BBB8AB6E2C\/vbe_501.zip\">Download<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Durch Anpassung des Ribbons oder des Backstage-Bereichs kann man seinen Anwendungen praktische Elemente zum Aufrufen von Funktionen, Formularen oder Berichten hinzuf&uuml;gen. Noch individueller werden benutzerdefinierte Ribbons und der Backstage-Bereich, wenn man den Steuerelementen auch noch eigene Icons hinzuf&uuml;gt. Das ist jedoch mit Bordmitteln nicht so einfach m&ouml;glich. Fr&uuml;her hat man diese Aufgabe unter Verwendung zahlreicher API-Funktionen aus der GDI-Bibliothek erledigt. Mittlerweile haben wir wesentlich einfachere Routinen daf&uuml;r entwickelt. In diesem Artikel stellen wir diese vor und zeigen, wie Du Ribbon- und Backstage-Steuerelemente einfach mit solchen Icons ausstatten kannst.<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"om_disable_all_campaigns":false,"_monsterinsights_skip_tracking":false,"_monsterinsights_sitenote_active":false,"_monsterinsights_sitenote_note":"","_monsterinsights_sitenote_category":0,"_uf_show_specific_survey":0,"_uf_disable_surveys":false,"footnotes":""},"categories":[66022026,662026,44000036],"tags":[],"yst_prominent_words":[],"class_list":["post-55000501","post","type-post","status-publish","format-standard","hentry","category-66022026","category-662026","category-Ribbon_programmieren"],"aioseo_notices":[],"_links":{"self":[{"href":"https:\/\/vbentwickler.de\/data\/wp\/v2\/posts\/55000501","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/vbentwickler.de\/data\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/vbentwickler.de\/data\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/vbentwickler.de\/data\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/vbentwickler.de\/data\/wp\/v2\/comments?post=55000501"}],"version-history":[{"count":0,"href":"https:\/\/vbentwickler.de\/data\/wp\/v2\/posts\/55000501\/revisions"}],"wp:attachment":[{"href":"https:\/\/vbentwickler.de\/data\/wp\/v2\/media?parent=55000501"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/vbentwickler.de\/data\/wp\/v2\/categories?post=55000501"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/vbentwickler.de\/data\/wp\/v2\/tags?post=55000501"},{"taxonomy":"yst_prominent_words","embeddable":true,"href":"https:\/\/vbentwickler.de\/data\/wp\/v2\/yst_prominent_words?post=55000501"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}