Outlook Ribbon XML – 150 Zeilen Code eingespart


Ich hatte mir vor einigen Jahren ein AddIn für Outlook 2003 gebastelt, welches mir ausgewählte Kontakte verarbeitet und Adressaufkleber druckt. Über die Jahre hinweg habe ich es nach Office 2007, von VB.NET nach C# und von VSTO 2005 SE nach VSTO 3.0 portiert. Nun bringt Outlook 2010 das Ribbon UI für den Explorer. Mein Add-In lief immer noch, jetzt im Add-Ins Tab integriert, sah aber natürlich unschön aus.

Also habe ich mich heute an die Arbeit gemacht, eine korrekte Integration in das Ribbon-Modell von Office 2010 zu bauen.

Das RibbonX für die Gruppe war schnell gebaut:

---------------------------------------------------------------------------------

<ribbon>
  <tabs>
    <tab idMso="TabContacts">
      <group id="groupCM" label="Contact Manager"
             insertAfterMso="GroupViewGallery">
        <button id="btnCreateLabels" label="Create Labels"…
                onAction="onCreateLabels"/>
        <button id="btnSendMails" label="Send Email" …
                onAction="onSendMail"/>
        <button id="btnCheckAddresses" label="Validate Address" …
                onAction="onCheckAddress"/>
      </group>
    </tab>
  </tabs>
</ribbon>

---------------------------------------------------------------------------------

Dank Integration in den TabContacts fiel gleich die Prüfung weg, ob sich der Benutzer in den Kontakten aufhält und natürlich auch der (reichlich unlesbarer) Code zum Erzeugen der Menüeinträge:

---------------------------------------------------------------------------------

Office.CommandBar menuBar = olEx.CommandBars["Menu Bar"];
ContactManager =
   (Office.CommandBarPopup)menuBar.Controls.Add
      (Office.MsoControlType.msoControlPopup, 1,
       null, menuBar.Controls.Count, true);
ContactManager.Caption = "Contact Manager";
ContactManager.Visible = false;

mnuLabelMaker =
   (Office.CommandBarButton)ContactManager.Controls.Add
      (Office.MsoControlType.msoControlButton, 1,
       null, 1, true);
mnuLabelMaker.Caption = "Create Labels";
mnuLabelMaker.Tag = "_Labels";
mnuLabelMaker.Click +=
   new Microsoft.Office.Core.
     _CommandBarButtonEvents_ClickEventHandler(LabelClickHandler);
mnuLabelMaker.Visible = true;

---------------------------------------------------------------------------------

Adé, lieber Code, wir brauchen Dich nicht mehr.

Allerdings versuchte Outlook nun auch, denselben Ribbon-Eintrag beim Öffnen eines einzelnen Kontakts anzuzeigen, was natürlich fehl schlug:

image

Ja, da war doch noch etwas: An der Stelle, wo das Ribbon XML geladen wird, kann man einschränken (IRibbonExtensibility Members):

---------------------------------------------------------------------------------

public string GetCustomUI(string ribbonID)
{
  if (ribbonID == "Microsoft.Outlook.Explorer")
    return GetResourceText("ContactManager.MainRibbon.xml");
  else
    return string.Empty;

}

---------------------------------------------------------------------------------

Wo bekommt man nun die ribbonID her?

Der Ribbon Designer hat eine Property RibbonType, wo man alle Typen aufgelistet bekommt:

RibbonTypes

Die Ribbon Callbacks sind wieder einfach:

---------------------------------------------------------------------------------

public void onCreateLabels(Office.IRibbonControl control)
{
     Globals.ThisAddIn.CreateLabelsFromRibbon();
}

---------------------------------------------------------------------------------

Jetzt noch schnell die Kontextmenüeinträge bauen und fertig ist der Laden. … Ganz so schnell ging es dann doch nicht. Welches Kontextmenü ist das richtige und wie heißt es?

Die Namen und IDs der Menüs und Befehle sind hier zu finden (mehrere einzelne Excel-Files). Die Datei für den Outlook Explorer öffnen und die Spalte Tab nach “None (Context Menu)” fiiltern. Danach kann man in der Spalte daneben die Namen der Kontextmenüs finden (Duplikate entfernen):

ContextMenuAttachments ContextMenuNoteSystemMenu
ContextMenuCalendarItem ContextMenuQuickFlags
ContextMenuCalendarView ContextMenuRemoteDocument
ContextMenuCalendarViewFreeBusyBar ContextMenuSearchRoot
ContextMenuCalendarViewTimeBar ContextMenuShortcut
ContextMenuCardView ContextMenuStore
ContextMenuCategories ContextMenuTableArrangeBy
ContextMenuContactItem ContextMenuTableView
ContextMenuContactsMoreActions ContextMenuTableViewColumn
ContextMenuFlaggedContactItem ContextMenuTaskItem
ContextMenuFlaggedMailItem ContextMenuTimelineView
ContextMenuFolder Group/Context Menu Name
ContextMenuGroupHeader MenuCalendarNewItem
ContextMenuIconView MenuContactsNewItem
ContextMenuJournalItem MenuJournalNewItem
ContextMenuMailItem MenuMailNewItem
ContextMenuMailMoreActions MenuNotesNewItem
ContextMenuMultipleItems MenuTasksNewItem
ContextMenuNoteItem

 

Das Kontextmenü für einen einzelnen Kontakt war schnell gefunden: ContextMenuContactItem. Allerdings stellte sich heraus, dass bei mehreren ausgewählten Kontakten wieder ein anderes angezeigt wurde. Mit ein bisschen Suchen kam ich auf ContextMenuMultipleItems. (Die Doku dazu könnte ein wenig hilfreicher sein) Das RibbonX dafür sieht dann so aus:

---------------------------------------------------------------------------------

<contextMenus>
  <contextMenu idMso="ContextMenuContactItem"> 
    <button id="ctxCreateLabels" label="Create Labels" …
            onAction="onCreateLabels" insertAfterMso="Copy"/>
  </contextMenu>
  <contextMenu idMso="ContextMenuMultipleItems">
    <button id="ctxCreateLabelsMI" label="Create Labels" … 
            onAction="onCreateLabels" insertAfterMso="Copy"/>
  </contextMenu>
</contextMenus>

---------------------------------------------------------------------------------

Die Vorgängerversion bediente sich noch des Outlook-Objektmodells und sah (auszugsweise) so aus:

---------------------------------------------------------------------------------

olEx.Application.ItemContextMenuDisplay +=
   new Microsoft.Office.Interop.Outlook
       .ApplicationEvents_11_ItemContextMenuDisplayEventHandler
       (Application_ItemContextMenuDisplay);

void Application_ItemContextMenuDisplay(
           Microsoft.Office.Core.CommandBar CommandBar,
           Microsoft.Office.Interop.Outlook.Selection Selection)

{
   if (ContactView)
  {
    mnuCtxLabelMaker =
       CommandBar.Controls.Add(
          Office.MsoControlType.msoControlButton, 
          missing,
          missing,
          missing,
          true) as Office.CommandBarButton;
    mnuCtxLabelMaker.BeginGroup = true;
    mnuCtxLabelMaker.Caption = "Create Labels";
   
mnuCtxLabelMaker.Tag = "Create_Labels";
    mnuCtxLabelMaker.FaceId = 65;

    mnuCtxLabelMaker.Click += new Microsoft.Office.Core.
      _CommandBarButtonEvents_ClickEventHandler(LabelClickHandler);
    mnuCtxLabelMaker.Visible = true; 
    …
  }
  …
}

---------------------------------------------------------------------------------

Nicht sonderlich schön. Besonders, wenn man das schon etwas kryptische Event-Prinzip von Outlook betrachtet. Da faßt sich doch Ribbon XML viel besser an.

 

Das Endergebnis ist nun folgendes:

 

1. Ribbon-Integration im Outlook Explorer:

image

2. Ribbon-Integration in das Kontextmenü für einen einzelnen Kontakt:

Snip2

2. Ribbon-Integration in das Kontextmenü für mehrere ausgewählte Kontakte:

Snip1

Alles in allem habe ich etwa 150 Zeilen alten Code eingespart, wofür ich vielleicht ein Fünftel davon in neuen Code (RibbonX und Callbacks) investiert habe.

 

siehe auch: Show and Hide Context Menu Items in Outlook 2010

Comments (0)

Skip to main content