Adding Custom Dynamic Menus to the Office Fluent User Interface

This content is outdated and is no longer being maintained. It is provided as a courtesy for individuals who are still using these technologies. This page may contain URLs that were valid when originally published, but now link to sites or pages that no longer exist.

Summary:  Adding controls, such as dynamic menus and buttons, to the 2007 Microsoft Office Fluent user interface requires only a few lines of XML and programming code.

Office Visual How To

Applies to:  2007 Microsoft Office System, Microsoft Office Excel 2007

Frank Rice, Microsoft Corporation

June 2007


The 2007 Microsoft Office Fluent user interface (UI) replaces the current system of layered menus, toolbars, and task panes with a simpler system that is optimized for efficiency and discoverability. The Ribbon is a part of the Office Fluent UI, as are shortcut menus, the Quick Access Toolbar, and the Microsoft Office check box. You can add a number of custom and built-in controls, such as buttons, check boxes, and combo boxes, to the Office Fluent Ribbon. You add components to the Office Fluent Ribbon by using XML markup elements, and you set properties on those components by using attributes. You assign functionality to the components by using any programming language supported by Microsoft Visual Studio 2005, such as Microsoft Visual Basic and Microsoft Visual C#, and also Microsoft Visual Basic for Applications (VBA), Microsoft Visual C++, and Microsoft Visual Basic 6.0.

See It splash screen for video

Watch the Video

Length: 9:06 | Size: 10.0 MB | Type: WMV file

Code It | Read It | Explore It

Code It

Whether you want to add your own custom controls to the Office Fluent Ribbon, or reuse one of the many built-in controls, you use a combination of XML and programming code.

Adding Controls with XML

XML provides a hierarchical, declarative model of the Office Fluent Ribbon. You add controls, such as buttons and menus, to the Office Fluent Ribbon by using XML elements to specify the type of component. For example, you add a single button by using the button element. You assign property values to the button by using attributes such as the label attribute. Examine the following sample.

<customUI xmlns="" loadImage="LoadImage" >
   <ribbon startFromScratch="false">
         <tab id="tab1" label="Menu Demo" keytip="x" >
            <group id="group1" label="Demo Group">
               <menu id="menu1" 
                  label="Text Handler" 
                  supertip="This is a super tip for the menu." 
                  image="camera.bmp" >
                  <button id="button1" 
                     label="My Button" 
                     onAction="OnAction" />
                  <dynamicMenu id="dynamicMenu1" 
                     label="Dynamic Menu" 
                     getContent="GetContent" />

This sample adds a custom tab titled Menu Demo to the Office Fluent Ribbon by assigning text to the tab element's label attribute. This tab contains the Demo Group group, which contains a menu control named menu1. The menu control contains a custom button named button1 and a dynamic menu named dynamicMenu1.

You define properties for the controls by using attributes such as label, itemSize, and image. You assign these properties explicitly by setting the attribute equal to a string, such as the supertip attribute, or indirectly by pointing to a programming code procedure such as the getScreentip attribute. Figure 1 shows the result of applying this XML to the Office Fluent Ribbon in Microsoft Office Excel 2007.

Figure 1. Modified Ribbon Example in Office Excel 2007

Modified Ribbon Example in Office Excel 2007

Examining the other attributes of the controls, first, you assign the id attribute for the menu control. You can create custom user-defined controls on the Office Fluent Ribbon or use built-in functionality that is part of Microsoft Office. By using the id attribute, you indicate to Microsoft Office that this is a custom control. However, if you use the idMso attribute and point to the name of a built-in feature, this indicates to Microsoft Office that this control uses built-in functionality. For example, if you added a button to the Office Fluent Ribbon and set the idMso attribute equal to bold, clicking this button applies bold to whatever text you highlighted in the worksheet.


To find the name of the built-in Microsoft Office commands in Office Excel 2007, click the Microsoft Office Button, click Excel Options, click the Customize tab, and move the mouse pointer over the command. The name of the command is in parentheses.

Next, you explicitly set the label attribute equal to text instead of pointing the attribute to a procedure. Then set the itemsize attribute to large to indicate that size of the menu control. The choices for a control's size when set explicitly are normal and large. You can also set the size by using a callback procedure. Callback procedures are described in Assigning Functionality to Ribbon Components.

Next, you see the getScreentip attribute. ScreenTips are those small boxes that appear when you move the mouse pointer over an object on the Office Fluent Ribbon. They provide information about the object you are pointing to. Likewise, the supertip attribute (or the getSupertip attribute, if you are pointing to a callback procedure) provides additional information about the object.

Another thing to notice about the getScreentip and the supertip attributes is that whenever you see an attribute prefixed by the word get, that attribute points to a callback procedure. Therefore, in the code, the getScreentip attribute points to the callback procedure named GetScreentip.


You are not required to name callback procedures the same as the attribute with which they are used. You can just as easily use the following line of code: getScreentip="DoSomething". Also, you are not required to prefix attributes that point to callback procedures with the word get. For example, in the XML code, the onAction attribute points to a callback named OnAction. For more information about which attributes are assigned explicitly and which attributes point to callbacks, see Customizing the 2007 Office Fluent Ribbon for Developers (Part 1 of 3).

Next, the image attribute specifies a custom image for the button. Likewise, the imageMso attribute for button2 specifies a built-in image for the button. To find a spreadsheet of built-in images, see the 2007 Office System Add-In: Icons Gallery.

Inside the menu control, I defined a button named button1. After assigning the id attribute, I assigned the imageMso attribute equal to HappyFace. Because I used the imageMso attribute instead of the image attribute, the image must be one that is built into Microsoft Office.

Next, you see the getDescription attribute to which I assigned the GetDescription callback procedure. This attribute adds descriptive text when the button is displayed. Figure 1 shows the descriptive text for the button.

The onAction attribute points to a callback procedure that executes when you click the button. This procedure is discussed in the next section.

Following the button, I also added a dynamicMenu control to which I assigned three attributes. I already discussed the id and label attributes. The getContent attribute points to a callback procedure that creates a menu at run time, hence the name dynamic menu. The GetContent callback procedure is also discussed in the next section.

Assigning Functionality to Ribbon Components

In the previous XML sample, some attributes point to callback procedures. For example, the button element has an onAction attribute. When the button is clicked, the OnAction method, or callback procedure, is called. The code in the OnAction method gives the button its functionality. These procedures are called callbacks because when the button is clicked, this action alerts Microsoft Office that the control needs its attention. Microsoft Office then calls back to the method defined by the onAction attribute and performs whatever action is contained in the method. The following paragraphs describe these callback procedures in more detail.

The getScreentip attribute points to the GetScreenTip callback procedure. In this example, the procedure returns a string to Microsoft Office that appears when you move the pointer over the check box.

Public Function GetScreenTip(ByVal control As IRibbonControl) As String
    Return "This is a screen tip for the menu."
End Function
public string GetScreenTip(IRibbonControl control)
    return "This is a screen tip for the menu.";

The GetDescription callback procedure for the button control returns a String value to Microsoft Office that displays a possible description of the control.

Public Function GetDescription(ByVal control As IRibbonControl) As String
    Return "Your description here."
End Function
public string GetPressed(IRibbonControl control)
    return "Your description here.";

Next comes the LoadImage callback. When the Office Fluent Ribbon is initially loaded, the procedure that the imageLoad attribute points to in the customUI element is called. Then, whenever a control's custom image needs to be displayed for a control, the custom image is loaded from the embedded resource image file.

Public Function LoadImage(ByVal imageName As String) As Bitmap
    Dim assembly As Assembly = Assembly.GetExecutingAssembly()
    Dim stream As Stream = assembly.GetManifestResourceStream("RibbonDemo." & imageName)

    Return New Bitmap(stream)
End Function
public Bitmap LoadImage(string imageName)
    Assembly assembly = Assembly.GetExecutingAssembly();
    Stream stream = assembly.GetManifestResourceStream("RibbonDemo." + imageName);

    return new Bitmap(stream);

The OnAction callback procedure is called when you click the button. In this example, the procedure tests the Id property of the calling control and either displays a dialog box or inserts text that is specific to that control into the A1 cell in the worksheet.

Public Sub OnAction(ByVal control As IRibbonControl)
    Select Case control.Id
           Case "button1" : MessageBox.Show("You clicked the Happy Face button.")
           Case "button2" : applicationObject.Range("A1").Value = "You selected the Insert Text button."
           Case "button3" : applicationObject.Range("A1").Value = "You selected the Insert More Text button."
        End Select
End Sub
public void OnAction(IRibbonControl control, bool pressed)
    switch (control.Id)
        case "button1" : MessageBox.Show("You clicked the Happy Face button."); break;
        case "button2" : applicationObject.Range("A1").Value = "You selected the Insert Text button."; break;
        case "button3" : applicationObject.Range("A1").Value = "You selected the Insert More Text button."; break;
        default: MessageBox.Show("There was a problem."); break;

The dynamicMenu control includes the getContent attribute that points to the GetContent callback procedure.

Public Function GetContent(ByVal control As IRibbonControl) As String
    Dim MyStringBuilder As StringBuilder = New StringBuilder("<menu"" >")
    MyStringBuilder.Append("<button id=""button2"" label=""Insert Text"" onAction=""OnAction"" imageMso=""SignatureLineInsert"" />")
    MyStringBuilder.Append("<menuSeparator id=""menusep1"" getTitle=""GetTitle"" />")
    MyStringBuilder.Append("<button id=""button3"" label=""Insert More Text"" onAction=""OnAction"" imageMso=""FileDocumentInspect"" />")
    Return MyStringBuilder.ToString
End Function 
public string GetContent(IRibbonControl control)
    StringBuilder MyStringBuilder = new StringBuilder(@"<menu"" >");
    MyStringBuilder.Append(@"<button id=""button1"" label=""Insert Text"" onAction=""OnAction""  imageMso=""SignatureLineInsert"" />");
    MyStringBuilder.Append(@"<menuSeparator id=""menusep1"" getTitle=""GetTitle"" />");
    MyStringBuilder.Append(@"<button id=""button2"" label=""Insert More Text"" onAction=""OnAction"" imageMso=""FileDocumentInspect"" />");
    return MyStringBuilder.ToString();

This procedure uses the StringBuilder object to create a menu control as a String. The menu includes two buttons and a menuSeparator control. You can also see that I set several properties for the controls, which were discussed earlier. This control is created at run time, which means that it is not created until the menu control on the Office Fluent Ribbon is clicked.

Finally, the menuSeparator control calls the GetText callback procedure instead of explicitly assigning text to the attribute.

Public Function GetTitle(ByVal control As IRibbonControl) As String
    Return "menu separator title"
End Function
public string GetTitle(IRibbonControl control)
    return "menu separator title"

Read It

There are two ways to deploy a custom Office Fluent Ribbon:

  • Modify an Office Open XML Formats file created by one of the Microsoft Office applications that support the Office Fluent UI.

  • Use an add-in.

You can select the technique depending on the scope you need for the customized Office Fluent Ribbon. For example, modifying an Open XML Formats file results in document-level customization where the customized Office Fluent Ribbon is associated with a particular document rather than the entire application. Alternatively, by using an add-in, you get application-level customization, which means that the customized Office Fluent Ribbon applies to the entire application regardless of which document is open.

Creating a customized Office Fluent Ribbon by using an Open XML file is relatively simple.

  1. Open the document as a .zip file by changing the file name extension.

  2. Add a folder that contains the XML Ribbon customization code.

  3. Modify the document's relationship file to point to the custom folder.

  4. Change the document's file name extension.

  5. Open the document in the Microsoft Office application.

  6. Add code to the document to give the custom Office Fluent Ribbon its functionality.

Using an add-in to customize the Office Fluent Ribbon is equally simple. After creating the add-in project, you implement the IRibbonExtensibility interface, which is included in the Microsoft.Office.Core namespace. This interface contains one method called GetCustomUI. You use this method to return the XML Ribbon customization code to Microsoft Office. Then you add programming procedures that give the custom Office Fluent Ribbon its functionality.

Adding Custom Controls to the Ribbon

In the following procedure, you combine the information discussed earlier to create a custom tab that contains a group, a button, and a dynamic menu that contains two buttons and a menu separator.

Creating the Add-In Solution

To create the project, there are nine steps.

To create the project

  1. Start Visual Studio 2005.

  2. On the File menu, point to New, and then click Project.

  3. In the New Project dialog box, in the Project Types pane, expand Other Project Types, click Extensibility, and then select Shared Add-in.

  4. In the Name box, type RibbonDemo and then click OK to create the project.

  5. On the first page of the Shared Add-in Wizard, click Next.

  6. On the Select a Programming Language page, select either Visual C# or Visual Basic, and then click Next.

  7. On the Select an Application Host page, clear all the selections except Microsoft Excel, and then click Next.

  8. On the Enter a Name and Description page, optionally, type a name and description for the project, and then click Next.

  9. On the Choose Add-in Options page, select I would like my Add-in to load when the host application loads, click Next, and then click Finish.

Visual Studio creates a solution that contains two projects—the add-in itself, and a Setup project. (The Setup project enables you to install the add-in on other users' computers, and it makes it easier for you, at design time, to install and uninstall the add-in.)

Adding References to the Project

To interact with Office Excel 2007 and the Office Fluent Ribbon object model, add a reference to the Microsoft Office Core type library.

To add a reference library to the project

  1. In Solution Explorer, expand the References folder.

    If you do not see the References folder, on the Project menu, click Show All Files.

  2. Delete the Microsoft.Office.Core reference.

  3. Right-click the References folder, and then click Add Reference.

  4. Click the COM tab, select Microsoft Office 12.0 Object Library, and then click OK.

  5. At the top of the open code file, add the following statements to the project.

    Imports Microsoft.Office.Core
    Imports Excel = Microsoft.Office.Interop.Excel
    using Microsoft.Office.Core;
    using Excel = Microsoft.Office.Interop.Excel;

Creating the Ribbon Customization XML File

Create the file that adds the components and sets the property for those components.

To create the customization XML file

  1. On the Project menu, click Add New Item.

  2. In the Add New Item dialog box, select XML File. Name the new file Ribbon.xml, and then click Add.

  3. In the new XML file, add the XML markup that is in the Adding Controls with XML section.

Adding the XML File as an Embedded Resource

For best results, use the XML file as a resource within the project's resource file.

To set the XML file as an embedded resource

  1. In Solution Explorer, select Ribbon.xml.

  2. In the Properties window, select the Build Action property, and then select Embedded Resource in the list of options.

  3. On the Project menu, click RibbonDemo Properties.

  4. Click the Resources tab.

  5. In Solution Explorer, drag Ribbon.xml onto the Resources design surface.

    This action creates a file-based resource. From now on, the Ribbon.xml file is automatically stored as an application resource, and you can retrieve this content by using Visual Basic or Visual C# language features.

  6. Close the Resources window. When prompted, click Yes to save the resources.

Accessing the Host Application and Working with the Ribbon

Next, you create an instance of Excel and add the Office Fluent Ribbon interface.

To create an instance of Excel and implement the IRibbonExtensibility interface

  1. In Solution Explorer, right-click Connect.cs or Connect.vb, and then click View Code.

  2. Find the existing declaration for the applicationObject variable, and modify it so that it refers to an Excel.Application object. That is, modify the declaration so that it looks like the following code.

    Private applicationObject As Excel.Application
    private Excel.Application applicationObject;
  3. Modify the existing first line of the OnConnection method, which creates an instance of the Excel.Application object.

    applicationObject = DirectCast(application, Excel.Application)
    applicationObject =(Excel.Application)application;
  4. In Visual Basic, modify the line of code, near the top of the class that starts with Implements, adding support for implementing the IRibbonExtensibility namespace. Visual Basic inserts the GetCustomUI procedure automatically.

    Implements Extensibility.IDTExtensibility2, IRibbonExtensibility
  5. If you are coding in C#, at the end of the public class Connect : statement, add a comma and then type the following interface name.

  6. Continuing in C#, right-click the interface you just added, click Implement Interface, and then click Implement Interface Explicitly. This adds a stub for the only IRibbonExtensibility interface member: GetCustomUI.

  7. Modify the GetCustomUI method so that it looks like the following code.

    Public Function GetCustomUI(ByVal RibbonID As String) As String _
       Implements Microsoft.Office.Core.IRibbonExtensibility.GetCustomUI
       Return My.Resources.Ribbon
    End Function
    string IRibbonExtensibility.GetCustomUI(string RibbonID)
      return Properties.Resources.Ribbon;
  8. Add each of the procedures discussed in the Assigning Functionality to the Ribbon Components section in this article depending on the programming language.

    Because this menu control uses a custom image, you must add your own image to the project by following these steps:

  9. In Solution Explorer, right-click the project name, point to Add, and then click Existing Item.

  10. Navigate to the image, select it, and then click Add.

  11. Select the image file, and in the Properties pane, in the Build Action property, click Embedded Resource.

  12. Right-click the project name again, and then click Properties.

  13. Click the Resources tab, and in Solution Explorer, drag the image file onto the Resources tab.

Testing the Project

Now you are ready to run the project.

To test the project

  1. On the File menu, click Save All.

  2. Exit Excel 2007 if it is running.

  3. On the Build menu, click Build Solution.

  4. In Solution Explorer, right-click RibbonDemoSetup, and then click Build.

  5. Right-click RibbonDemoInSetup, and then click Install.

    The RibbonDemo Setup Wizard appears.

  6. Click Next on each page, and then click Close on the last page.

  7. Start Excel.

    The Menu Demo tab appears. You also see the Group Demo group that contains two check boxes.

  8. Click the Text Handler drop-down list.

  9. Click My Button.

    Excel displays a dialog box.

  10. Click OK to close the dialog box.

  11. Click the Text Handler drop-down list again, and then point to the Dynamic menu.

  12. Click Insert Text.

    Excel inserts text into the worksheet at cell A1, as shown in Figure 2.

    Figure 2. Clicking the Insert Text check box to insert text in cell A1

    Click the Insert Text check box to insert text

  13. Click Insert More Text. The text in cell A1 changes.

  14. Exit Excel.

  15. In Visual Studio, in Solution Explorer, right-click RibbonDemoSetup, and then click Uninstall.

Explore It

There are a number of resources on customizing the Office Fluent user interface.