Customizing the 2007 Office Fluent Ribbon for Developers (Part 1 of 3)

Summary: Learn how to customize the 2007 Office Fluent user interface. Also learn how new features in Microsoft Visual Studio 2005 Tools for the 2007 Microsoft Office System support RAD development of Ribbon customizations. (40 printed pages)

Frank Rice, Microsoft Corporation

Ken Getz, MCW Technologies, LLC

Published: May 2006

Updated: October 2006

Applies to: Microsoft Office Access 2007, Microsoft Office Excel 2007, Microsoft Office Outlook 2007, Microsoft Office PowerPoint 2007, Microsoft Office Word 2007, Microsoft Visual Studio 2005 Tools for the 2007 Microsoft Office System, Microsoft Visual Studio 2005

Contents

  • An Improved User Interface

  • New Ways to Enhance the User's Experience

  • What About Existing Solutions?

  • Customizing the Fluent UI for Most Office Applications

  • Using Callbacks

  • Two Ways to Customize the Fluent UI

  • Adding Document-Based Add-ins to the Fluent UI

  • UI Customization in Access 2007

  • Creating an Access Application-Level Custom Ribbon

  • Loading Customizations at Run Time

  • Ribbon Customization Scenarios for Other Applications

  • Using COM Add-ins to Modify the Fluent UI

  • Working with Existing Command-Bar Add-Ins

  • Dynamically Updating the Fluent UI

  • Loading Images

  • Conclusion

  • Additional Resources

An Improved User Interface

Many of the applications in the 2007 Microsoft Office system have a new look. The new Microsoft Office Fluent user interface (UI) replaces the current system of layered menus, toolbars, and task panes with a simpler system optimized for efficiency and discoverability. The new Fluent UI has improved context menus, Enhanced ScreenTips, a Mini toolbar, and keyboard shortcuts that help to improve user efficiency and productivity.

NoteNote

The Fluent UI is implemented in several applications in the 2007 Microsoft Office release, including Microsoft Office Access 2007, Microsoft Office Excel 2007, Microsoft Office PowerPoint 2007, and Microsoft Office Word 2007. The Ribbon is also available in Microsoft Office Outlook 2007 while you edit an Outlook item. You can customize the Fluent UI through a combination of XML markup and any Microsoft .NET Framework–based language that is supported in Microsoft Visual Studio. You can also customize the Fluent UI by using Microsoft Visual Basic for Applications (VBA), Microsoft Visual C++, and Microsoft Visual Basic 6.0.

New Ways to Enhance the User's Experience

Developers have taken advantage of the tools and programming structures in earlier versions of Office to extend the Fluent UI in creative ways. For example, the command bars object model enabled developers to build rich solutions in their custom Office applications. Continuing in that tradition, UI extensibility introduces an innovative model that you can use to enhance the user experience. You use extensible markup language (XML) and one of several conventional programming languages to manipulate the components that make up the Fluent UI. Because XML is plain text, you can create customization files in any text editor, which simplifies work with the Fluent UI. You can also reuse custom Fluent UI files with a minimum of adjustments because each application uses the same programming model.

Figure 1. The Fluent UI in applications in the 2007 Office release

Ribbon UI

Using XML markup files to customize the Fluent UI greatly reduces the need for complex add-ins based on the command bars object model. However, add-ins written for previous versions of Office will continue to work in the Fluent UI with little or no modification.

What About Existing Solutions?

In previous versions of Office, developers used the command bars object model to build the Visual Basic code that modified the Fluent UI. In the 2007 release of Office, this legacy code continues to work in most cases without modification. However, changes made to toolbars in Microsoft Office 2003 now appear on an Add-Ins tab. The type of customization that appears depends on the original design of the add-in. For example, Office creates a Menu Commands group that contains items added to the previous menu structure (such as the File menu, the Insert menu, and the Tools menu). Office also creates a Toolbar Commands group that contains items added to the previous built-in toolbars (such as the Standard toolbar, the Formatting toolbar, and the Picture toolbar). In addition, custom toolbars that are added by an add-in or document appear in the Custom Toolbars group on the Add-Ins tab.

Customizing the Fluent UI for Most Office Applications

You can create a custom application-level Fluent UI in Word 2007, in Excel 2007, or in PowerPoint 2007 in the following ways:

  • By using COM add-ins in managed or unmanaged code

  • By using application-specific add-ins, such as .ppam and .xlam files

  • By using templates (.dotm files) in Word 2007

NoteNote

Access 2007 and Outlook 2007 implement Ribbon customizations in slightly different ways than the other Office applications do.

In a typical scenario, code in a COM add-in contains a procedure that returns XML markup from an external customization file or from XML contained in the code itself. When the application starts, the add-in loads and runs the code that returns the XML markup. The code validates the XML markup against an XSD schema (though that is optional), and then loads the XML into memory and applies it to the Fluent UI. The modified Fluent UI then appears. Fluent UI commands and controls use callback procedures to run code in the add-in.

Document-level customizations use the same XML markup and an Office Open XML Formats file with one of these extensions: .docx, .docm, .xlsx, .xlsm, .pptx, or .pptm. For these solutions, you create a customization file that contains the XML markup and save it to a folder. You then modify the parts in the Office Open XML Formats container to point to the customization file. When you open the document in the Office application, the application loads the customization file into memory and applies it to the Fluent UI. The commands and controls then call code contained in the document to provide functionality.

Using Callbacks

You specify callbacks to update properties and perform actions from your Fluent UI at run time. For example, to specify an action that occurs when the user clicks a button on the Ribbon, you must supply the onAction callback function for the button. The Ribbon extensibility markup looks like this:

<button id="myButton" onAction="MyButtonOnAction" />

This markup tells Office to call the MyButtonOnAction method when the button is clicked. The MyButtonOnAction method has a specific signature depending on your choice of languages; here is an example:

public void MyButtonOnAction (IRibbonControl control)
{
    if (control.Id == "myButton")
    {
        System.Windows.Forms.MessageBox.Show("Button clicked!");
    }
}
NoteNote

Depending on how you create your customization, you may need to add a reference to the System.Windows.Forms assembly to call the MessageBox.Show method.

The MyButtonOnAction procedure must be declared as public. The control parameter carries the unique id and tag properties of the control, which enables you to use the same callback procedure for multiple controls.

NoteNote

All attributes in the Ribbon XML customization markup use the camel-casing convention, which capitalizes the first character of each word except the first word—examples include onAction and insertBeforeMso.

Two Ways to Customize the Fluent UI

Applications that support the Ribbon (except Access 2007, as described Creating an Access Application-Level Custom Ribbon) provide two ways to customize the Fluent UI by using XML markup: by using Office Open XML Formats files that contain XML markup, or by using COM add-ins that contain XML markup. (In the case of Outlook, only COM add-ins can customize the Fluent UI.) Any changes that you specify in this XML markup add incrementally to the existing Fluent UI. For example, providing XML markup that identifies a custom tab adds a single tab to the existing tabs in the host application.

All controls in Ribbon extensibility markup must include one of the following identifiers.

Table 1. One of these identifiers must be used with all controls

Identifier

Description

id

Specifies a unique identifier for the control. Used with custom controls. This identifier is passed as a property on an IRibbonControl to callback functions.

idMso

Specifies the identifier of a built-in control.

idQ

Specifies a qualified identifier, prefixed with a namespace abbreviation, as in the following example.

NoteNote

The example uses the namespace x so that two different add-ins can add to the same custom group—they just need to refer to that custom group by its qualified name.

General Format of XML Markup Files

You can use XML markup to customize the Fluent UI. The following example shows the general format of an XML markup file that customizes the Fluent UI in Word 2007. Examples in the following sections use this markup.

<customUI xmlns="http://schemas.microsoft.com/office/2006/01/customui">
  <ribbon>
    <tabs>
      <tab idMso="TabHome">
        <group idMso="GroupFont" visible="false" />
      </tab>
      <tab id="CustomTab" label="My Tab">
        <group id="SampleGroup" label="Sample Group">
          <toggleButton id="ToggleButton1" size="large" 
            label="Large Toggle Button" 
            getPressed="ThisDocument.MyToggleMacro"
            onAction="ThisDocument.MyActionMacro"  />
          <checkBox id="CheckBox1" label="A CheckBox" 
            screentip="This is a check box" 
            onAction="ThisDocument.MyCheckboxMacro" />
          <editBox id="EditBox1" getText="ThisDocument.MyTextMacro" 
            label="My EditBox" onChange="ThisDocument.MyEditBoxMacro"/>
          <comboBox id="Combo1" label="My ComboBox" 
            onChange="ThisDocument.MyComboBoxMacro">
            <item id="Zip1" label="33455" />
            <item id="Zip2" label="81611" />
            <item id="Zip3" label="31561" />
          </comboBox>
          <dialogBoxLauncher>
            <button id="Launcher1" screentip="My Launcher" 
              onAction="ThisDocument.MyLauncherMacro" />
          </dialogBoxLauncher>
        </group>
        <group id="MyGroup" label="Sample My Group" >
          <button id="Button1" label="My Large Button" 
            size="large" onAction="ThisDocument.MyButtonMacro" />
          <button id="Button2" label="My Normal Button" 
            size="normal" onAction="ThisDocument.MyOtherButtonMacro" />
        </group >
      </tab>
    </tabs>
  </ribbon>
</customUI>

This XML markup results in a modified Fluent UI, as the following figure shows.

Figure 2. Sample of Fluent UI customization in Word

Sample of Ribbon UI customization in Word

This sample makes the following changes to the Fluent UI in Word 2007, in the order shown:

  1. The sample declares the default namespace for the XML markup.

  2. The sample hides the built-in GroupFont group that is located on the built-in Home tab.

  3. The sample adds a new CustomTab tab to the right of the last built-in tab, with the label My Tab.

    NoteNote

    Use the id identifier attribute to create a custom item, such as a custom tab. Use the idMso identifier attribute to refer to a built-in item, such as the TabHome tab.

  4. The sample adds a new Sample Group group to the My Tab tab.

  5. The sample adds a large-sized ToogleButton1 button to the Sample Group group. The markup specifies onAction and getPressed callbacks.

  6. The sample adds a CheckBox1 check box to the Sample Group group with a custom screentip. It also specifies an onAction callback.

  7. The sample adds an EditBox1 edit box to the Sample Group group and specifies an onChange callback.

  8. The sample adds a Combo1 combo box to the Sample Group group with three items and specifies an onChange callback.

  9. The sample adds a Launcher1 launcher to the Sample Group group with the onAction callback set.

    A launcher normally displays a custom dialog box that offers more options to the user.

  10. The sample adds a new Sample Group group to the custom tab.

  11. The sample adds a large-sized Button1 button to the Sample Group group and specifies a label and onAction callback.

  12. The sample adds a normal-sized Button2 button to the Sample Group group and specifies an onAction callback.

The easiest way to create Ribbon extensibility markup is to use a validating XML editor. Microsoft Visual Studio 2005 provides such an editor that you can use, if you can provide the necessary schema (XSD) file. In this case, you need a current copy of customUI.xsd, which is available in several places. For example, when you install Microsoft Visual Studio 2005 Tools for the 2007 Microsoft Office System (also known as Visual Studio 2005 Tools for Office Second Edition), it adds the schema to the Visual Studio schema catalog, so the schema is available by default in a Visual Studio project. You can also find the schema at the 2007 Office System: XML Schema Reference Web site. In Visual Studio, create a new XML file, and in the Properties window, set the Schemas property to include the customUI.xsd file (or enter the schema reference in the code, as shown in the previous XML document). Then, as you enter XML content into the file, you can take advantage of Microsoft IntelliSense technology. You might also find the XML Notepad 2006 download useful; it is available from the Microsoft Download Center. This tool enables you to edit and view XML content in a tree-based format.

Customizing the Fluent UI by Using Office Open XML Formats Files

At the document level, the process for customizing the Fluent UI by using XML markup involves the following steps. For more information, see Adding Document-Based Add-ins to the Fluent UI later in this article. You can follow these steps, using the XML markup described in the previous section.

NoteNote

Although it is useful to know what is going on within the Office Open XML Formats structure, you may be able to bypass these steps. You can take advantage of the Custom Fluent UI Editor, available at OpenXMLDeveloper.org. This tool enables you to open a document, insert custom UI, and then save the document with the Ribbon extensibility markup in place. It performs for you the steps listed in this example. It also enables you to add custom icons to the customUI folder, and makes it easy to refer to these icons. You can download the Custom UI Editor from the OpenXMLDeveloper.org Custom UI Editor Tool Web page.

To customize the Fluent UI by using Office Open XML Formats files

  1. Create a folder on your desktop named customUI.

  2. Create the customization file in any text editor by writing XML markup that adds new components to the Fluent UI, modifies existing components, or hides components. You can use the XML markup from the previous example, to test the behavior. Save the file as customUI.xml (or any other name) in the folder you just created.

  3. Validate the XML markup against your custom Fluent UI schema (optional).

  4. Create a document in the Office application, and then save it as an Office Open XML Formats file with one of these extensions: .docx, .docm, .xlsx, .xlsm, .pptm, or .pptx.

    File name extensions for files that contain macros have an "m" suffix. These files can contain procedures that can be called by Ribbon extensibility commands and controls.

    Caution noteCaution

    You must save the document in macro-enabled format if you want to add code that reacts when the user interacts with the Ribbon customization. Documents with this functionality include the .docm, .xlsm, and .pptm formats. For all the examples in this article that include Microsoft Visual Basic for Applications (VBA) code, you must save the host document as one of these formats.

  5. Exit the Office application.

  6. In Microsoft Windows Explorer, add the file name extension .zip to the document file name, and then double-click the file to open it as a compressed folder.

  7. Add the customization file to the container by dragging the customUI folder from the desktop to the compressed folder.

  8. Drag the _rels folder to the desktop. A folder named _rels containing the .rels file appears on the desktop.

  9. Open the new folder, and then open the .rels file in a text editor.

  10. Between the final <Relationship> element and the closing <Relationships> element, add a line that creates a relationship between the document file and the customization file. Ensure that you specify the folder and file names correctly (the Id attribute supplies a unique relationship ID for the customUI—its value is arbitrary).

    <Relationship Type="http://schemas.microsoft.com/office/2006/
      relationships/ui/extensibility" Target="/customUI/customUI.xml" 
      Id="customUIRelID" />
    
  11. Save the .rels file.

  12. Drag the .rels file from the desktop to the _rels folder in the compressed file, replacing the existing .rels file.

  13. Remove the .zip extension from the container file.

When you open the file in the Office application, the UI appears with your customizations. Depending on your application settings, if you use the markup from the previous section in this example, you might receive several warning messages as you open the document. Because you have not supplied the code that corresponds to the various callback procedures, you have not really created a complete custom UI yet.

Adding Document-Based Add-ins to the Fluent UI

The following steps outline the basic process for creating a document that contains a simple custom UI in Excel 2007 that can call a custom macro:

  1. Create a macro-enabled Excel workbook with one macro.

  2. Create a file to customize the Fluent UI by adding one tab, one group, and one button.

  3. Create a procedure in VBA that the Fluent UI calls, in response to the button being clicked.

  4. Specify the onAction callback attribute in the button's markup, so that it calls the macro you created in the document.

  5. Modify the contents of the macro-enabled document container so that it contains the file that customizes the Fluent UI.

  6. Save the macro-enabled file, and then open it in Excel 2007.

NoteNote

You can follow these same basic steps when creating a macro-enabled Word or PowerPoint document.

To create an Excel workbook that is macro-enabled

  1. Start Excel 2007.

  2. Click the Developer tab, and then click Visual Basic.

    NoteNote

    If you do not see the Developer tab, you must identify yourself as a developer. To do this in your application, click the Microsoft Office Button, click Application Options, click Popular, and then select Show Developer Tab in the Ribbon. This is a global setting that identifies you as a developer in all Office applications that implement the Fluent UI.

  3. In the Visual Basic Editor, double-click ThisWorkbook to open the Code window.

  4. Type the following VBA function, and then click the Excel icon in the left corner of the toolbar to return to Excel.

    Sub MyMacro(ByVal control as IRibbonControl)
       MsgBox("Hello World")
    End Sub
    
  5. Save the document as a macro-enabled workbook with the file name extension .xlsm.

    Note

    If you save the document as a standard .xlsx document, you will not be able to run the macro code. When you save the document, you must explicitly select the Save As menu option, and then select Excel Macro-Enabled Workbook (*.xlsm).

  6. Exit Excel.

To create the file that contains the XML markup to modify the Fluent UI

  1. Create a folder on your desktop named customUI.

  2. Create a new text file, add the following XML, and then save the file as customUI.XML in the customUI folder on your desktop.

    <customUI xmlns="http://schemas.microsoft.com/office/2006/01/customui"> 
      <ribbon startFromScratch="true"> 
        <tabs> 
          <tab id="CustomTab" label="My Tab"> 
            <group id="SimpleControls" label="My Group"> 
              <button id="Button1" imageMso="HappyFace" size="large" 
                label="Large Button" 
                onAction="ThisWorkbook.MyMacro" /> 
            </group> 
          </tab> 
        </tabs> 
      </ribbon> 
    </customUI>
    

To modify files contained in the macro-enabled file container

  1. In Windows Explorer, find the macro-enabled file you created. Rename the file by adding the .zip extension.

  2. In Windows Explorer, double-click the file to open it.

  3. Add the customization file to the container by dragging the customUI folder from the desktop to the compressed folder and clicking the Add button when prompted.

  4. Drag the _rels folder to the desktop.

  5. Open the new folder, and then open the .rels file in a text editor.

  6. Add the following text between the last <Relationship> element and the </Relationships> element, and then save and close the file.

    <Relationship Id="customUIRelID" Type="http://schemas.microsoft.com/office/2006/relationships/ui/extensibility" 
    Target="customUI/customUI.xml" />
    
  7. Drag the .rels file from the desktop to the _rels folder in the compressed folder, replacing the existing .rels file.

  8. Remove the .zip extension from the container file name.

  9. Open the macro-enabled file in Excel 2007. The custom UI replaces the built-in Fluent UI.

    NoteNote

    Depending on your security settings, you might see a security warning telling you that macros have been disabled. If you do, click the Options button that appears next to the warning, select Enable this content, and then click OK.

  10. Click Large Button. Clicking the button triggers the onAction callback, which calls the macro in the workbook, which displays the "Hello World" message.

Customizing the Fluent UI with COM Add-Ins

Customizations at the application level result in a modified Fluent UI that appears in the application regardless of which document is open. Generally, COM add-ins make these modifications. You generally have two options for creating COM add-ins by using managed code: You can use the Shared Add-In template that is included with Visual Studio 2005, or you can use Visual Studio 2005 Tools for Office Second Edition, which makes it even easier to create add-ins. The following steps describe the underlying method call sequence for a COM add-in that customizes the Ribbon. Although the concepts are the same no matter how you create the add-in, the specific code that you need to write will be different, as you will see in later sections of this article that walk you through examples that create add-ins, by using both techniques.

To customize the Fluent UI by using COM add-ins

  1. Create a COM add-in project.

    The add-in you create must implement the Extensibility.IDTExtensibility2 interface and the IRibbonExtensibility interface (found in the Microsoft.Office.Core namespace).

  2. Build the add-in and Setup project and then install the project.

  3. Start the Office application.

When the add-in loads, the IDTExtensibility2::OnConnection event is triggered, which initializes the add-in, just as in previous versions of Office.

Next, Office calls either the QueryInterface method (for unmanaged add-ins) or the QueryService method (for managed add-ins), which determines whether the add-in implements the IRibbonExtensibility interface. If it does, Office calls the IRibbonExtensibility::GetCustomUI method, which returns the XML markup (from an XML customization file or from XML markup embedded in the procedure), and then Office loads the customized Fluent UI into the application. Finally, the customized UI is ready for the user.

Caution noteCaution

Because of the internal architecture of the Ribbon callback mechanism, it is important that you perform no initialization within the GetCustomUI method other than preparing and returning the XML markup for the Ribbon. Specifically, do not display dialog boxes or message windows from within this callback method.

Each control specified in the XML markup exposes its functionality by calls to callback procedures. For example, the XML markup for a button control can specify an onAction attribute that points to a procedure that is executed when the user clicks the button. In most cases, the callback procedure exposes an IRibbonControl interface that identifies the control. The callback might pass other arguments as well, such as a Boolean object that specifies the state of a toggle button as pressed or not pressed. The IRibbonControl interface implements three properties: the Context object, the Id object, and the Tag property. The Context object is the active window that contains the Ribbon that triggers the callback. The Id object is the string identifier of the custom control specified in the markup. The Tag property is a non-unique property that you can optionally specify in the markup.

UI Customization in Access 2007

Ribbon extensibility customizations in Access 2007 share some of the same options that the other Office applications have, but with some important differences. Just as with the other applications, you customize the Fluent UI in Access by using XML markup. And like the other applications, you can use external files that contain XML markup or COM add-ins to integrate Ribbon customizations into your application. However, unlike the other Office applications, because Access database files are binary and cannot be opened as Office Open XML Formats files, you cannot customize the Access Ribbon by adding parts to the database file.

Access does provide flexibility in customizing the Fluent UI. For example, customization markup can be stored in a table, embedded in a VBA procedure, stored in another Access database, or linked to from an Excel worksheet. You can also specify a custom UI for the application as a whole or for specific forms and reports.

The following scenarios can give you an idea of how to customize the Access UI.

NoteNote

Because these walkthroughs involve changes to the database, you might want to perform these steps in a non-production database, perhaps by using a backup copy of a sample database.

Customizing the Fluent UI in Access

When customizing the Access UI, you have two choices: You can store your customizations in a special table and have Access automatically load the markup for you, or you can store the customizations in a location of your choosing and load the markup manually by calling the Application.LoadCustomUI method.

If you choose to have Access load the customizations for you, you need to store them in a table named USysRibbons. The table should have at least two columns: a 255-character Text column named RibbonName, and a Memo column named RibbonXML. You place the Ribbon name in the RibbonName column, and the Ribbon markup in the RibbonXML column. After you close and re-open the database, you can select the default Ribbon to use in the Access Properties dialog box. You can select a Ribbon to appear when any form or report is selected as a property of the form or report.

If you decide to use a more dynamic technique, you can call the LoadCustomUI method, which loads Ribbon customizations whether the XML content is stored in a table or not. After you have loaded the customizations by calling LoadCustomUI, you can programmatically assign the named customization at run time.

NoteNote

Customizations that you load by using the LoadCustomUI method are available only while the database is open. You need to call LoadCustomUI each time you open the database. This technique is useful for applications that need to assign custom UI programmatically at run time.

The signature for the LoadCustomUI method is as follows.

expression.LoadCustomUI(CustomUIName As String, CustomUIXML As String)

expression returns an Application object.

CustomUIName is the name of the Custom Ribbon ID to be associated with this markup.

CustomUIXML contains the XML customization markup.

There is an example of using the LoadCustomUI method Loading Customizations at Run Time.

The following procedure describes, in a generalized manner, how to add application-level customizations in Access. A later section includes a complete walkthrough.

To apply a customized application-level Ribbon at design time

  1. Create a table named USysRibbons with columns as described earlier. Add rows for each different Ribbon you want to make available.

  2. Close and then reload the database.

  3. Click the Microsoft Office Button, and then click Access Options.

  4. Click the Current Database option and then, in the Ribbon and Toolbar Options section, click the Ribbon Name drop-down list and click one of the Ribbons.

To remove an existing customization (so that your database uses the default Fluent UI), delete the existing Ribbon name from the Ribbon Name list, and leave an empty value for the name of the Ribbon.

The following procedure describes, in a generalized manner, how to add form-level customizations or report-level customizations in Access.

To assign a specific custom Ribbon to a form or report

  1. Follow the process described previously to make the customized Ribbon available to the application, by adding the USysRibbons table.

  2. Open the form or report in Design view.

  3. On the Design tab, click Property Sheet.

  4. In the Property window, on the Other tab, click the Ribbon Name drop-down list, and then click one of the Ribbons.

  5. Save, close, and then re-open the form or report. The UI you selected is displayed.

    NoteNote

    The tabs displayed in the Fluent UI are additive. That is, unless you specifically hide the tabs or set the Start from Scratch attribute to True, the tabs displayed by a form or report's UI appear in addition to the existing tabs.

To explore this process further, work through the following examples.

The first part of the example sets an option that reports any errors that exist when you load custom UI (although you are performing these steps in Access, you can perform similar steps in other applications).

Creating an Access Application-Level Custom Ribbon

To create an Access application-level custom ribbon

  1. Start Access. Open an existing database, or create a new database.

  2. Click the Microsoft Office Button, click Access Options, and then click the Advanced tab.

  3. In the General section, select the option Show add-in user interface errors (this option might be in a different location, in different applications).

  4. Click OK to close the Access Options dialog box.

    Next, create a table that contains your customization XML markup.

  5. With a database open in Access, right-click the Navigation pane. Point to Navigation Options, and then click Show System Objects. (You cannot view the USysRibbons table in the Navigation pane unless this option is set.) Click OK to dismiss the dialog box. The Access system tables appear in the Navigation pane.

  6. On the Create tab, click Table Design.

  7. Add the following fields to the table.

    Table 2. USysRibbons table field definitions

    Field Name

    Type

    ID

    AutoNumber

    RibbonName

    Text

    RibbonXml

    Memo

  8. Select the ID field. On the Design tab, select Primary Key.

  9. Click the Microsoft Office Button, and then click Save. Name the new table USysRibbons.

  10. Right-click the USysRibbons tab, and then click Datasheet View.

  11. Add the following data to the fields you created.

    Table 3. USysRibbons table data

    Field Name

    Value

    ID

    (AutoNumber)

    RibbonName

    HideData

    RibbonXml

    This markup sets the startfromScratch attribute to False, and then hides the built-in Create tab. Next, it creates a custom tab and a custom group, and adds the built-in Paste control to the group.

  12. Close the table.

  13. Close and then re-open the database.

  14. Click the Microsoft Office Button, and then click Access Options.

  15. Click the Current Database tab, and scroll down until you find the Ribbon and Toolbar Options section.

  16. In the Ribbon Name drop-down list, select HideData. Click OK to dismiss the dialog box.

  17. Close and re-open the database.

    The Edit group is no longer displayed, and the Fluent UI includes the A Custom Tab tab, which contains the A Custom Group group with the Built-in Paste button.

    Figure 3. The Access application-level UI

    The Access application-level Ribbon UI

  18. To clean up, repeat the previous few steps to display the Access Options dialog box. Delete the contents of the Ribbon Name option, so that Access displays its default Fluent UI after you close and re-open the database.

    NoteNote

    You can also use a Ribbon from the USysRibbons table to supply the UI for a specific form or report. To do this, open the form or report in Design or Layout mode, and set the form's RibbonName property to the name of the Ribbon you want to use. You must select the form itself, rather than any control or section on the form, before you can set this property.

Loading Customizations at Run Time

If you want to load static customizations at run time, you can store those customizations in the USysRibbons table, and set a form or report's RibbonName property as necessary. But, if you need to create dynamic customizations, call the Application.LoadCustomUI method. The following example creates a Ribbon customization that displays a button for each form in the application, and handles the onAction callback for each button to load the requested form.

To create a dynamic Ribbon customization

  1. Load the database that you worked with in the previous section into Access 2007. If your database does not already include more than one form, create a few forms, and add a control or two to each form.

  2. On the Create tab, in the Other group, click the drop-down list of the Macro button, and then click Module.

  3. In the Visual Basic Editor, on the View menu, click Properties Window.

  4. In the Properties window, in the Name property box, change the name of the module to RibbonLoader.

  5. In the code window, insert the following code. Even though this method does not return a value, it must be a function—otherwise, you cannot call it from an Access macro.

    Function CreateFormButtons()
      Dim xml As String
      xml = _
       "<customUI http://schemas.microsoft.com/" & _
       "office/2006/01/customui"">" & vbCrLf & _
       "  <ribbon startFromScratch=""false"">" & vbCrLf & _
       "    <tabs>" & vbCrLf & _
       "      <tab id=""DemoTab"" label=""LoadCustomUI Demo"">" & _
         vbCrLf & _
       "        <group id=""loadFormsGroup"" label=""Load Forms"">" & _
         vbCrLf & _
       "{0}" & vbCrLf & _
       "        </group>" & vbCrLf & _
       "      </tab>" & vbCrLf & _
       "    </tabs>" & vbCrLf & _
       "  </ribbon>" & vbCrLf & _
       "</customUI>"
    
      Dim template As String
      template = "<button id=""load{0}Button"" " & _
       "label=""Load {0}"" onAction=""HandleOnAction"" " & _
       "tag=""{0}""/>" & vbCrLf
    
      Dim formContent As String
      Dim frm As AccessObject
      For Each frm In CurrentProject.AllForms
        formContent = formContent & _
         Replace(template, "{0}", frm.Name)
      Next frm
    
      xml = Replace(xml, "{0}", formContent)
      Debug.Print xml
      On Error Resume Next
      ' If you call this code from the AutoExec macro,
      ' the only way it can fail is if you have a
      ' customization with the same name in the
      ' USysRibbons table.
      Application.LoadCustomUI "FormNames", xml
    End Function
    

    When you run the code, it creates markup that might look like the following XML, if your application contains two forms named Form1 and Form2.

    <customUI xmlns="http://schemas.microsoft.com/office/2006/01/customui">
      <ribbon startFromScratch="false">
        <tabs>
          <tab id="DemoTab" label="LoadCustomUI Demo">
            <group id="loadFormsGroup" label="Load Forms">
              <button id="loadForm2Button" label="Load Form2" 
                onAction="HandleOnAction" tag="Form2"/>
              <button id="loadForm1Button" label="Load Form1" 
                onAction="HandleOnAction" tag="Form1"/>
            </group>
          </tab>
        </tabs>
      </ribbon>
    </customUI>
    

    This markup creates a new LoadCustomUI Demo tab that contains a Load Forms group. Within the group, the Ribbon displays a button for each form in the application (Form1 and Form2), and indicates that each button should call the HandleOnAction callback procedure when clicked. In addition, the markup sets the Tag attribute for each button so that it contains the name of the Access form that your code should open.

  6. Add the following procedure to the same module. This procedure supplies the callback behavior. It opens the selected form and sets its RibbonName property to the FormNames Ribbon customization.

    Public Sub HandleOnAction(control As IRibbonControl)
        ' Load the specified form, and set its
        ' RibbonName property so that it displays
        ' the custom UI.
        DoCmd.OpenForm control.Tag
        Forms(control.Tag).RibbonName = "FormNames"
    End Sub
    
  7. Save the database, and close the Visual Basic Editor.

  8. If your application does not contain at least two forms, create forms until the application contains at least two forms.

  9. Decide which one of your forms should be your application's startup form, and open that form in Design view.

  10. In the Properties window, on the Event tab, find the onLoad event property. Click the ellipsis (...) button to the right of the property value, select Code Builder in the list of options, and then click OK. (If you do not see the Properties window, on the Design tab, click Property Sheet.)

  11. In the Visual Basic Editor, modify the Form_Load procedure so that it looks like the following code.

    Private Sub Form_Load()
        CreateFormButtons
        Me.RibbonName = "FormNames"
    End Sub
    
  12. On the Tools menu, click References. Select Microsoft Office 12.0 Object Library (you need a reference to this object library to use the IRibbonControl class), and then click OK.

  13. Save the database and close the Visual Basic Editor.

  14. Click the Microsoft Office Button, and then click Access Options.

  15. Click the Current Database tab.

  16. In the Application Options section, select your startup form in the Display Form list of forms, and then click OK.

  17. Close and re-open the database.

    The startup form opens, along with a custom tab that contains a group that displays a button for each form in your application. Click any of the buttons: Access opens the corresponding form, maintaining the same custom UI.

In addition to the described techniques, you can add Ribbon customizations to Access by using a COM add-in. COM add-ins provide the benefit of adding custom Ribbon extensibility functionality as a package without the need to add VBA code to each application. Add-ins are implemented in Access just as they are in other Office applications.

NoteNote

Although you can use the Visual Studio 2005 Shared Add-In template to create a COM add-in for Access, you cannot use Visual Studio 2005 Tools for Office Second Edition to create COM add-ins for Access. Access is not one of the supported applications in Visual Studio 2005 Tools for Office Second Edition.

Ribbon Customization Scenarios for Other Applications

Consider the following scenarios that illustrate ways to modify the Fluent UI to fit your needs.

NoteNote

To demonstrate the behavior of the Ribbon customizations in the following sections, you can use the techniques discussed earlier in this article, in the section titled Customizing the Fluent UI for Most Office Applications.

Creating Custom Solutions

Although each example you have seen so far modifies the existing Ribbon, you can create your entire UI from scratch. You might do this if you want to build your own UI and design your own custom layout for the Ribbon. If you set the Ribbon element's startFromScratch attribute to True, the Ribbon hides all of its content (so you do not have to do the work to hide everything manually). When you set the startFromScratch attribute to True, it makes the following changes:

  • Hides all the existing Ribbon tabs, including the Add-Ins tab

  • Modifies the Microsoft Office menu to include only the New, Open, Save, Application Options, and Exit commands

    Caution noteCaution

    You can specify in the XML markup file that you want to hide the controls on the Microsoft Office menu. You must explicitly request these alterations in the XML markup by setting the Visible attribute for the particular control to False. Hiding these commands might put the application into an unrecoverable state that you can clear only by closing the application and uninstalling your solution.

Setting the startFromScratch attribute makes no changes to the status bar, which remains present.

The following sample XML markup uses the startFromScratch attribute to customize the Fluent UI.

<customUI xmlns="http://schemas.microsoft.com/office/2006/01/customui" >
  <ribbon startFromScratch="true" >
    <tabs>
      <tab id="CustomTab" label="My Tab" >
        <group id="SimpleControls" label="My Group">
          <toggleButton id="ToggleButton1"
            size="large" label="Large Toggle Button"/>
          <button id="Button2" label="My Button " />
          <comboBox id="Combo1" label="ComboBox">
            <item id="Month1" label="January" />
            <item id="Month2" label="February" />
            <item id="Month3" label="March" />
          </comboBox>
        </group>
      </tab>
    </tabs>
  </ribbon>
</customUI>

This sample hides all of the built-in components in the Fluent UI and replaces them with a custom tab, one group, and various controls.

Showing and Hiding Tabs

You can use markup like the following sample to show or hide built-in tabs or custom tabs.

<tab idMso="TabHome" visible="false" />

If you want to programmatically determine whether to show or hide a tab (or other element), you can provide a callback procedure. That is, you can define the element as in the following XML.

<tab idMso="TabInsert" getVisible="getVisibleCallback" />

Then, in an add-in, or within VBA code, you can provide a procedure that returns a Boolean value that indicates whether the item is visible. For example, you might use code like the following to hide the Insert tab in Word 2007 on weekends.

Public Sub getVisibleCallback(control As IRibbonControl, _
    ByRef visible As Variant)
    Select Case DatePart("w", Date)
        Case vbSaturday, vbSunday
            visible = False
        Case Else
            visible = True
    End Select
End Sub

Showing and Hiding Groups

You can use code like the following sample (along with the callback procedure in the previous example) to show or hide built-in groups or custom groups.

<tab idMso="TabView">
  <group idMso="GroupDocumentViews" visible="false" />
  <group id="MyCustomGroup" label="Custom Group" 
    getVisible="getVisibleCallback" />
</tab>

Adding Custom Tabs

You can use the following code sample to add custom tabs.

<tab id="CustomTab" label="My Tab" />

Adding Custom Groups with Controls

You can use the following code sample to add a custom group, and then add built-in controls.

<group id="CustomGroup" label="My Group"> 
   <toggleButton idMso="Italic" /> 
   <toggleButton idMso="Bold" /> 
   <button idMso="FileSave" /> 
</group> 

You can use the following code to add a custom group, and then add custom controls.

<group id="CustomGroup" > 
   <toggleButton id="MyToggleButton" size="large" 
     label="Insert My Object"/> 
   <checkBox id="AllowChanges" label="Allow Changes" /> 
   <dropDown id="ChooseDepartment" showLabel="true" 
     label="Choose Department"> 
      <item id="Dept1" label="Shipping" /> 
      <item id="Dept2" label="Accounting" /> 
      <item id="Dept3" label="Engineering" /> 
   </dropDown> 
</group>

Creating a Custom Menu with Nested Menus and Controls

You can use the following code sample to create a custom menu, and then add nested built-in menus and controls and custom menus and controls. This markup also includes two menu separators, with and without text.

<menu id="MyMenu" label="Test Menu" itemSize="normal"> 
   <toggleButton idMso="Bold"/> 
   <button id="MenuButton1" label="Button1" /> 
   <menuSeparator id="separator1"/>
   <toggleButton id="MenuToggleButton1" label="ToggleButton" /> 
   <button idMso="FileExit"/> 
   <menu id="Nested1" label="Advanced" itemSize="normal"> 
      <button idMso="Cut"/> 
      <button idMso="Copy"/> 
      <button idMso="Paste"/> 
      <menuSeparator id="separator2" title="Large Buttons Below"/>
        <menu id="Nested2" label="Large" itemSize="large"> 
        <button idMso="Cut"/> 
         <button idMso="Copy"/> 
        <button idMso="Paste"/> 
      </menu> 
   </menu> 
</menu>

Adding Combo Boxes or Drop-Down Boxes with Nested Items

You can use the following code sample to add a built-in combo box control with items (drop-down controls use the same syntax).

<comboBox id="ComboBox1" label="ComboBox"> 
    <item id="item1" label="one" imageMso="_1" /> 
    <item id="item2" label="two" imageMso="_2" /> 
    <item id="item3" label="three" imageMso="_3" /> 
</comboBox>

You can use the following code sample to add gallery controls with items, and then add a custom button control.

<gallery id="MonthGallery" imageMso="DateAndTimeInsert" 
  label="Pick a Month:" columns="3" rows="4" onAction="InsertMonth" >
  <item id="Month1" label="January"/>
  <item id="Month2" label="February"/>
  <item id="Month3" label="March"/>
  <item id="Month4" label="April"/>
  <item id="Month5" label="May"/>
  <item id="Month6" label="June"/>
  <item id="Month7" label="July"/>
  <item id="Month8" label="August"/>
  <item id="Month9" label="September"/>
  <item id="Month10" label="October"/>
  <item id="Month11" label="November"/>
  <item id="Month12" label="December"/>
  <button id="InsertMonthButton" 
    label="Insert current month" onAction="InsertCurrentMonth"/>
</gallery>

The following VBA procedures provide callback behavior for the gallery items and the button within the gallery.

Sub InsertMonth(control As IRibbonControl, _
    selectedId As String, selectedIndex As Integer)

    Dim text As String
    Select Case control.ID
        Case "MonthGallery"
            text = monthName(selectedIndex + 1)
    End Select
    Selection.InsertAfter text
End Sub

Sub InsertCurrentMonth(control As IRibbonControl)
    Select Case control.ID
        Case "InsertMonthButton"
            text = monthName(DatePart("m", Date))
    End Select
    Selection.InsertAfter text
End Sub
NoteNote

When you define the gallery, all item elements must appear before any button elements.

You can populate gallery controls at run time by using callbacks. You can use the getItemCount callback to determine the number of items to display, the getItemHeight and getItemWidth callbacks to retrieve the height and width of the items in the gallery, the getItemImage and getItemLabel callbacks to retrieve the image and label for each item, and the getSelectedItemID or getSelectedItemIndex callback to retrieve the selected ID or index.

Filling a Drop-Down List Dynamically

You might not know which items to display in a Ribbon control until run time. Callbacks make it possible to supply the values based on current conditions. For example, you might want to display a list of document headings. The following example demonstrates how you might provide a list of current document headings.

Include the following control in your Ribbon customization.

<dropDown id="HeadingsDropDown" 
  getItemCount="GetItemCount" 
  getItemID="GetItemID" 
  getItemLabel="GetItemLabel"/>

Then, in your code (in this case, in a module within the Word document's Visual Basic Editor), add the following callback procedures.

Sub GetItemCount(control As IRibbonControl, ByRef count)
    Dim varItems As Variant
    varItems = ActiveDocument.GetCrossReferenceItems(wdRefTypeHeading)
    count = UBound(varItems)
End Sub

Sub GetItemLabel(control As IRibbonControl, index As Integer, _
    ByRef label)
    Dim varItems As Variant
    varItems = ActiveDocument.GetCrossReferenceItems(wdRefTypeHeading)
    label = varItems(index + 1)
End Sub

Sub GetItemID(control As IRibbonControl, index As Integer, ByRef ID)
    ID = "heading" & index
End Sub

Now, when you open the drop-down list, it shows all the headers in your document.

Grouping Individual Controls

By default, the Ribbon determines the positions of controls that you add to a group. If you want to define the layout of the controls with more precision, you can group the controls within one or more boxes. When you create a box, you specify its orientation (horizontal or vertical). A group can contain multiple boxes, and you can include vertical dividers between the boxes. (The vertical dividers are created by using the separator control, which is used only for vertical boxes.)

The following example sets up three groups, one that uses horizontal boxes, one that uses vertical boxes, and one that uses no boxes. Figure 4 shows the results.

<group id="CustomGroup1" label="Horizontal Boxes" 
   insertBeforeMso="GroupClipboard">
  <box id="box1" boxStyle="horizontal">
    <button id="buttonA1" label="Button1"/>
    <button id="buttonA2" label="Button2"/>
  </box>
  <box id="box2" boxStyle="horizontal">
    <button id="buttonAA" label="ButtonA"/>
    <button id="buttonAB" label="ButtonB"/>
    <button id="buttonAC" label="ButtonC"/>
  </box>
</group>
<group id="CustomGroup2" label="Vertical Boxes" 
   insertBeforeMso="GroupClipboard">
  <box id="box3" boxStyle="vertical">
    <button id="buttonB1" label="Button1"/>
    <button id="buttonB2" label="Button2"/>
  </box>
  <separator id="separator2"/>
  <box id="box4" boxStyle="vertical">
    <button id="buttonBA" label="ButtonA"/>
    <button id="buttonBB" label="ButtonB"/>
    <button id="buttonBC" label="ButtonC"/>
  </box>
</group>
<group id="CustomGroup3" label="No Boxes" 
   insertBeforeMso="GroupClipboard">
  <button id="buttonC1" label="Button1"/>
  <button id="buttonC2" label="Button2"/>
  <button id="buttonCA" label="ButtonA"/>
  <button id="buttonCB" label="ButtonB"/>
  <button id="buttonCC" label="ButtonC"/>
</group>

Figure 4. Different box styles

Different box styles

Using COM Add-ins to Modify the Fluent UI

You can use COM add-ins to modify the Fluent UI. When you decide to create a COM add-in that incorporates Ribbon customization and uses managed code, you have two distinct choices. You can create a standard shared add-in, using the Shared Add-In template that comes with Visual Studio 2005. Or, if you have installed Visual Studio 2005 Tools for Office Second Edition, you can create a COM add-in that has several advantages over the standard shared add-in.

Among other advantages, add-ins that you create by using Visual Studio 2005 Tools for Office Second Edition run in separate application domains, and the programming model for these add-ins is simpler, and more maintainable, than that used by the shared add-in template. For more information, see Migrating a Shared Add-in to a Visual Studio 2005 Tools for the Office System SE Add-in.

Using a Shared Add-in Project to Modify the Fluent UI

The following example uses a managed COM add-in to add a custom UI to Word 2007. The add-in creates a custom tab, a group, and a button. When you click the button, the add-in inserts a company name at the location of the cursor.

To create the add-in solution

  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 InsertCompanyAddIn, 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 of the selections except Microsoft Word, and then click Next.

  8. On the Enter a Name and Description page, type InsertCompanyAddIn for the name and Insert Company Name for the description, 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 new 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.)

To interact with Word 2007 and the Ribbon object model, add references to two type libraries.

To add references

  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 Word = Microsoft.Office.Interop.Word
    
    using Microsoft.Office.Core;
    using Word = Microsoft.Office.Interop.Word;
    

To create an XML customization 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 following XML markup.

    <customUI xmlns="http://schemas.microsoft.com/office/2006/01/customui">
      <ribbon>
        <tabs>
          <tab id="CustomTab" label="My Tab">
            <group id="SampleGroup" label="Sample Group">
              <button id="Button" label="Insert Company Name" 
                size="large" onAction="InsertCompanyName" />
            </group>
          </tab>
        </tabs>
      </ribbon>
    </customUI>
    
  4. Save and close the file.

It is easiest to use the XML file if it is treated as a resource within the project's resource file.

To create the XML 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 InsertCompanyAddIn Properties.

  4. Click the Resources tab.

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

    This action creates a new file-based resource that contains the XML content. 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.

To access the host application and work with the Ribbon

  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 a Word.Application object. That is, modify the declaration so that it looks like the following code.

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

    applicationObject = DirectCast(application, Word.Application)
    
    applicationObject =(Word.Application)application;
    
  4. (Visual Basic only) 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. (C# only) At the end of the public class Connect : statement, add a comma and then type the following interface name.

    IRibbonExtensibility
    
  6. (C# only) 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;
    }
    
    Caution noteCaution

    GetCustomUI should be implemented to return the XML string for your Ribbon customization, and should not be used for initialization. In particular, you should not attempt to display any dialog boxes or message windows in your GetCustomUI implementation. The more appropriate place to do initialization is in the OnConnection method (for shared add-ins) or in the ThisAddIn_Startup method (for add-ins created by using Visual Studio 2005 Tools for Office Second Edition).

  8. Add the following method to the class. This method inserts the company name into the document at the current cursor location.

    Public Sub InsertCompanyName(ByVal control As Office.IRibbonControl)
      ' Inserts the specified text at the current location
      ' in the document.
      Dim companyName As String = "Microsoft Corporation"
      applicationObject.Selection.InsertAfter(companyName)
    End Sub
    
    public void InsertCompanyName(Office.IRibbonControl control)
    {
      // Inserts the specified text at the current location 
      // in the document.
      string companyName = "Microsoft Corporation";
      applicationObject.Selection.InsertAfter(companyName);
    }
    
  9. On the File menu, click Save All.

  10. Exit Word 2007 if it is running.

  11. On the Build menu, click Build Solution.

  12. In Solution Explorer, right-click InsertCompanyAddInSetup, and then click Build.

  13. Right-click InsertCompanyAddInSetup, and then click Install.

    The InsertCompanyAddIn Setup Wizard appears.

  14. Click Next on each of the pages, and then click Close on the last screen.

  15. Start Word.

    The My Tab tab appears to the right of the other tabs.

  16. Click My Tab, and then click Insert Company Name. Word inserts the specified company name into the document at the cursor location.

  17. Exit Word.

  18. In Visual Studio, in Solution Explorer, right-click InsertCompanyAddInSetup, and then click Uninstall.

Using a Visual Studio 2005 Tools for Office Second Edition Project to Modify the Fluent UI

This example shows how to create the same add-in as in the previous example, but this time by using Visual Studio Tools 2005 Tools for Office Second Edition.

To create the project

  1. Start Visual Studio 2005 Tools for Office Second Edition.

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

  3. In the New Project dialog box, select Visual Basic or Visual C#.

  4. In the Project Types pane, expand the Office node, and select 2007 Add-ins.

  5. In the Templates pane, select Word Add-in.

  6. Name the new add-in InsertCompanyAddIn1, and then click OK to create the new add-in.

Visual Studio creates a new solution containing 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 to install and uninstall the add-in at design time.)

Note that although the new add-in implements the IExtensibility2 interface, you do not see all the procedures required by this interface. Instead, Visual Studio 2005 Tools for Office Second Edition creates a simple class named ThisAddIn, and provides the procedures you are likely to need. You can add code to the ThisAddIn_Startup method or to the ThisAddin_Shutdown method, as appropriate. For this example, you do not need code in either method. You also do not need to modify code or set references to create the add-in—all the connection work has been done for you.

To add a Ribbon extensibility item

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

  2. In the Add New Item dialog box, select Ribbon Support.

  3. Click Add to accept the default name (Ribbon1.vb or Ribbon1.cs).

    The template adds an XML file named Ribbon1.xml, and a new class to your project. The XML file contains a very simple customized UI. The new Ribbon1 file contains a commented-out extension of the ThisAddIn class, and a new class named Ribbon1.

  4. In Solution Explorer, double-click Ribbon1.xml to open it in the XML editor.

  5. Modify the existing XML, so that it looks like the following markup.

    <customUI xmlns="http://schemas.microsoft.com/office/2006/01/customui" 
              onLoad="onLoad">
      <ribbon>
        <tabs>
          <tab id="CustomTab" label="My Tools Tab">
            <group id="SampleGroup" label="Sample Group">
              <button id="Button" label="Insert Company Name" 
                size="large" onAction="InsertCompanyName" />
            </group>
          </tab>
        </tabs>
      </ribbon>
    </customUI>
    
  6. Save the XML file and close the XML editor.

It is easiest to use the XML file if it is treated as a resource within the project's resource file.

To create the XML resource

  1. On the Project menu, click InsertCompanyAddIn1 Properties.

  2. Click the Resources tab.

  3. From Solution Explorer, drag Ribbon1.xml onto the Resources design surface.

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

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

To modify the Ribbon code and complete the add-in

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

  2. In the Code Editor, select the partial class named ThisAddIn, and uncomment the partial class.

    The RequestService procedure enables the Visual Studio 2005 Tools for Office Second Edition runtime to determine which class should handle callbacks for the add-in's Ribbon customization. If this procedure is passed a GUID corresponding to the IRibbonExtensibility interface, it returns its IRibbonUI instance, if it has one. If not, it passes control to the RequestService method of its base class.

    NoteNote

    By default, the RequestService method appears in a comment because your add-in might already include an override for this method (perhaps for the FormRegionStartup interface, or one of the other new extensibility interfaces). If that is the case, you can copy the if block from the commented code into your existing override for this method.

  3. In the Ribbon1 class, modify the GetCustomUI procedure so that it returns the XML from the Ribbon1 resource, rather than calling the add-in's GetResourceText procedure.

    Return My.Resources.Ribbon1
    
    return Properties.Resources.Ribbon1;
    
    NoteNote

    The add-in template includes, within the Helpers hidden region, a procedure named GetResourceText that retrieves the contents of the XML file for you. Although this procedure does the job you need, it requires you to specify the name of the resource as a string. This technique is somewhat brittle (changes to the resource name would still allow the code to compile, but the add-in would fail at run time), so it is better to add the XML content to the resource file and use the language-specific support for retrieving resources, as shown in these steps. The template includes the GetResourceText procedure so that it can work "out of the box"—when you create and build an add-in, you have a working Ribbon customization without any changes.

  4. In the Ribbon1 class, add a public declaration for a variable that can refer to the Word Application object.

    Public Application As Word.Application
    
    public Word.Application Application;
    
  5. In the same file, in the ThisAddIn partial class, immediately below the line of code that creates the instance of the Ribbon1 class, add code that sets the Ribbon1 class' Application property.

    ' In the RequestService method:
    ribbon.Application = Application
    
    // In the RequestService method:
    ribbon.Application = Application;
    
  6. Add the following procedure to the Ribbon1 class, so that you can handle the onAction callback for the new button in the Ribbon and insert the company name at the cursor location in the document.

    Public Sub InsertCompanyName(ByVal control As IRibbonControl)
      ' Inserts the specified text at the current location
      ' in the document.
      Dim companyName As String = "Microsoft Corporation"
      Application.Selection.InsertAfter(companyName)
    End Sub
    
    public void InsertCompanyName(IRibbonControl control)
    {
      // Inserts the specified text at the current location 
      // in the document.
      string companyName = "Microsoft Corporation";
      Application.Selection.InsertAfter(companyName);
    }
    

To test the add-in

  1. On the File menu, click Save All.

  2. Press F5 to run the project, which also starts Word 2007.

  3. Click the My Tools Tab tab, and then click Large Button.

    The code inserts the company name at the cursor location in the document.

  4. Exit Word 2007.

You can build the Setup project and install the add-in just as you did in the previous example. In this case, Visual Studio 2005 Tools for Office Second Edition makes it easier to run (and debug) add-ins. Press F5, and the project runs as you might expect. You can get the same behavior with the shared add-in template—you just need to set the project properties that indicate which application you want to run when you press F5, and select the correct Office application. You might find it instructive to debug the add-in, and add a breakpoint to the code.

Working with Existing Command-Bar Add-Ins

When you create COM add-ins, you usually need a way for users to interact with the add-in. In earlier versions of Office, you accomplished this by adding a menu item or toolbar button to the application by using the command bars object model. In the 2007 release of Office, custom applications continue to work in the Fluent UI without modification in most cases. However, changes you make with the command bars object model, or with any other technology that modifies the menus or toolbars, such as WordBasic or XLM, appear on a separate Add-Ins tab. This helps users locate the controls they need to work with and the add-ins they used previously.

Figure 5. A custom toolbar button added to the Add-Ins tab in Excel 2007

The Add-Ins tab in Excel 2007

To make changes to the items in the Fluent UI, you can use the techniques and code already described. For existing add-ins that change the menu structure, the commands appear on the Add-Ins tab. For information about how to update existing add-ins, see the technical article Migrating a Shared Add-in to a Visual Studio 2005 Tools for the Office System SE Add-in.

Dynamically Updating the Fluent UI

Callbacks that return properties of a control (such as the gallery control's getItemCount callback) normally get called only as the Fluent UI initializes, unless you explicitly force the control to re-initialize. You can force this to happen by storing a reference to the Ribbon in your code, and then calling methods of the Ribbon that invalidate an individual control or the entire Ribbon. To do this, you must add the onLoad attribute, specifying a callback procedure, in the <customUI> element. The onLoad callback is called once, when the Ribbon extensibility markup file is successfully loaded. The callback procedure receives an IRibbonUI object as a parameter—your code can cache this reference for later use. The IRibbonUI class provides methods that enable you to invalidate a single control or the entire Ribbon.

To cache the IRibbonUI object so you can update your controls at run time, you might add code like this:

<customUI xmlns="http://schemas.microsoft.com/office/2006/01/customui" 
  onLoad="ribbonLoaded">

In your code (VBA code within a document, or perhaps Visual Basic code or C# code in an add-in), add a procedure like the following code.

IRibbonUI myRibbon;

public void ribbonLoaded(IRibbonUI ribbon) 
{
  myRibbon = ribbon;
}

The IRibbonUI interface exposes the following methods.

Table 4. Methods of the IRibbonUI interface

Method

Action

Description

Invalidate()

callback

Causes all of your custom controls to re-initialize.

InvalidateControl(string controlID)

callback

Causes a particular control to re-initialize.

Loading Images

The <customUI> element's loadImage attribute enables you to specify a callback that can load all images. After you set up this callback procedure, Office calls the callback procedure and passes the string from the image attribute for each control that loads images. You do not need to implement the getImage callback multiple times, such as one time for each control that requires images. For example, a customization might include markup like the following.

<customUI xmlns="http://schemas.microsoft.com/office/2006/01/customui" 
  loadImage="GetImage">
<!-- Later in the markup -->
   <button id="myButton" image="mypic.jpg" />

To supply the button's image, Office calls the GetImage function. It passes the parameter "mypic.jpg" and expects an IPictureDisp object in return. By using this technique, you can write a single callback procedure that returns all the images your customization needs, without having to write each individual control's getImage callback. Note that the loadImage callback is not called again when you call the Ribbon's Invalidate method or InvalidateControl method. For the controls that need to change images dynamically at run time, use the getImage callback.

For example, you could use the code from the following example to provide your customization's images. The getImage callback method must return a stdole.IPictureDisp type, so you usually need to convert your images to this type. To perform these conversions, you can use the following PictureConverter class, which inherits from the AxHost class.

Friend Class PictureConverter
  Inherits AxHost

  Private Sub New()
    MyBase.New(String.Empty)
  End Sub

  Public Shared Function ImageToPictureDisp( _
    ByVal image As Image) As stdole.IPictureDisp
    Return CType(GetIPictureDispFromPicture(image), _
      stdole.IPictureDisp)
  End Function

  Public Shared Function IconToPictureDisp( _
    ByVal icon As Icon) As stdole.IPictureDisp
    Return ImageToPictureDisp(icon.ToBitmap())
  End Function

  Public Shared Function PictureDispToImage( _
    ByVal picture As stdole.IPictureDisp) As Image
    Return GetPictureFromIPicture(picture)
  End Function
End Class
internal class PictureConverter : AxHost
{
  private PictureConverter() : base(String.Empty) { }

  static public stdole.IPictureDisp ImageToPictureDisp(Image image)
  {
    return (stdole.IPictureDisp)GetIPictureDispFromPicture(image);
  }

  static public stdole.IPictureDisp IconToPictureDisp(Icon icon)
  {
    return ImageToPictureDisp(icon.ToBitmap());
  }

  static public Image PictureDispToImage(stdole.IPictureDisp picture)
  {
    return GetPictureFromIPicture(picture);
  }
}

Then, your callback procedure might look something like this, assuming that you had added an icon to your project resources named MyIcon.

Public Function GetImage( _
  ByVal imageName As String) As stdole.IPictureDisp
  Return PictureConverter.IconToPictureDisp(My.Resources.MyIcon)
End Function
public stdole.IPictureDisp GetImage(string imageName)
{
  return
    PictureConverter.IconToPictureDisp(Properties.Resources.MyIcon);
}
NoteNote

Your project must have a reference set to the stdole assembly to run this code. This reference is automatically included in projects created by using Visual Studio 2005 Tools for Office Second Edition.

Conclusion

Customizing the UI in previous versions of Office meant creating COM add-ins or DLL files for each application that shared the add-in. By contrast, the Ribbon feature uses text-based, declarative XML markup that simplifies creating and customizing the Ribbon. With a few lines of XML, you can create just the right interface for the user. Because the XML markup is contained in a single file, modifying the interface as requirements change is much simpler. You can also improve user productivity by putting the commands where users can find them more easily. The Ribbon adds consistency across applications, which reduces the time users spend learning each application.

Additional Resources

To learn more about the products and technologies mentioned or used in this article, see these resources: