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

Summary: This article is the companion to the part one and part two articles of the same name. This article contains a list of frequently asked questions regarding the Microsoft Office Fluent user interface. (33 printed pages)

Frank Rice, Microsoft Corporation

Ken Getz, MCW Technologies, LLC

Published: May 2006

Updated: May 2008

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

Contents

  • The Ribbon and the Office Fluent User Interface

  • Ribbon and Office Fluent UI Frequently Asked Questions

  • Conclusion

  • Additional Resources

The Ribbon and the Office Fluent User Interface

The Ribbon is a part of the new Microsoft Office Fluent user interface (UI) for some of the applications in the 2007 release of Microsoft Office, including Microsoft Office Access 2007, Microsoft Office Excel 2007, Microsoft Office Outlook 2007, and Microsoft Office Word 2007. The Office Fluent UI is a departure from the system of menus, toolbars, and dialog boxes that were part of earlier releases of Office.

Ribbon and Office Fluent UI Frequently Asked Questions

These are some of the questions that are asked most frequently about how to customize the Fluent UI.

When I moved to Beta 2 TR, I noticed some differences in element names. What are these, specifically?

The <advanced> element was renamed to <dialogBoxLauncher>. The <fileMenu><menu id="fileMenu"> element was renamed to <officeMenu>. A loadImage callback was added with the following signatures.

Sub LoadImage(imageID, ByRef image)
public object loadImage(string imageId)

In addition, many of the idMso values changed.

How do you expose the internal IDs of built-in controls?

You can see each individual idMso value within the applications by using the following procedure.

To find the idMso value for an application

  1. Click the Microsoft Office Button, and then click Application Options.

  2. Click Customize, and then select the item you want information about.

  3. Move the pointer over the item. The dialog box displays the control's idMso value in a ScreenTip, in parentheses.

What are the control IDs for controls that I need to disable or repurpose?

There are a set of Ribbon controls whose published control IDs are not the same as control IDs that should be used for their disabling/repurposing. This is due to how these specific controls are implemented internally. These previously unpublished control IDs only apply to the <commands> section of the XML used to define the Ribbon when repurposing and disabling commands. For all other scenarios (inserting controls with insertAfterMso/insertBeforeMso, cloning controls with <control idMso=""/>, re-using images with imageMso, and so forth), the published control ID is the correct ID.

The following table lists the affected IDs–the second column is the published control ID, and the third column is the ID that should be used to disable or repurpose the controls.

Table 1. Control IDs for disabling and repurposing controls

Control Type

Control ID

Control ID for Disabling/Repurposing

button

AlternativeText

ObjectSizeAndPropertiesDialog

gallery

Drawing1ColorPickerFill

ShapeFillColorPicker

gallery

Drawing1ColorPickerFillWordArt

ShapeFillColorPicker

gallery

Drawing1ColorPickerLineStyles

OutlineColorPicker

gallery

Drawing1ColorPickerLineStylesWordArt

OutlineColorPicker

gallery

Drawing1GalleryBrightness

PictureBrightnessGallery

gallery

Drawing1GalleryContrast

PictureContrastGallery

gallery

Drawing1GalleryTextures

ShapeFillTextureGallery

button

FileSaveAsOtherFormats

FileSaveAs

gallery

GalleryAllShapesAndCanvas

ShapesInsertGallery

gallery

GalleryAllShapesAndTextboxes

ShapesInsertGallery

checkBox

GridlinesExcel

ViewSheetGridlines

gallery

InsertBuildingBlocksEquationsGallery

EquationInsertGallery

gallery

PictureBorderColorPickerClassic

OutlineColorPicker

gallery

PictureShapeGallery

ShapeChangeShapeGallery

button

PlayMacro

MacroPlay

gallery

ShapeOutlineColorPicker

OutlineColorPicker

gallery

ShapeQuickStylesHome

ShapeStylesGallery

checkBox

ShowRuler

ViewRulerWord

gallery

TableTextStylesGallery

TextStylesGallery

button

UnmergeCells

SplitCells

checkBox

ViewGridlines

ViewGridlinesPowerPoint

checkBox

ViewHeadings

ViewSheetHeadings

What are some of the limitations on attributes that I need to know about?

  • The getShowImage, getShowlabel, showImage, showLabel attributes are ignored on large controls.

  • The description and getDescription attributes only apply to menu items.

  • The getSize and size attributes do not apply to menu items. Instead the size is based on the item size for menu items.

  • The getVisible and visible attributes are ignored for ButtonGroup and Separator elements.

How do I display error messages for the Fluent UI?

You can control the error message display by setting a general option in each application.

To display error messages for the Fluent UI

  1. Click the Microsoft Office Button, and then click Application Options to display the dialog box.

  2. Click Advanced, and then find the General section of the options.

  3. Select Show add-in user interface errors.

How do I change the UI dynamically? For example, I want to update labels and images, hide and show buttons, or refresh the content of a list while my code is running.

See the section "Dynamically Updating the Fluent UI" in the article Customizing the 2007 Office Fluent Ribbon for Developers (Part 1 of 3).

In Excel 2007, I am not able to run macros from the Quick Access Toolbar or from the Ribbon when my worksheet is in Print Preview. Is this the expected behavior?

Yes, this is the expected behavior. The ability to run macros while in Print Preview is disabled in Excel 2007. For example, assume that you have added a custom button to the Quick Access Toolbar. If you click the Microsoft Office Button, point to Print, and then click Print Preview, the current worksheet is displayed in Print Preview mode. The default buttons on the Quick Access Toolbar are disabled. If you then click the custom button, nothing happens; that is, any macro attached to the button is not executed and no dialog box is displayed.

Is there a way to programmatically control how the UI used by my add-in scales in size as controls are added or removed?

As currently implemented, custom groups do not resize themselves. They remain large, effectively getting a higher priority.

Is there a way to reset the UI and remove all customizations?

Yes. To reset the UI, uninstall your add-ins and then close any open documents. This restores the default UI.

Yes. You can dynamically fill the gallery by supplying callbacks for the getItemCount, getItemLabel, or getItemImage attributes.

Are custom controls in the Fluent UI supported?

No. As an alternative, for scenarios that are not supported by the built-in controls, you can use the custom task pane feature to host your custom controls. You can find more information in the article Creating Custom Task Panes in the 2007 Office System.

Are all the controls in the Office applications available to my own customizations?

No, some controls are not available. For example, the splitButtonGallery control is not available to your customizations. (An example of the splitButtonGallery control is the Text Highlight Color control in Word 2007.)

What parts of the Fluent UI are not customizable by using the new extensibility model?

You cannot customize the status bar, the Mini toolbar, or context menus, although you can customize context menus by using the command bars object model.

Can I turn off the Mini toolbar?

Yes. The following procedure gives the steps.

To turn off the Mini toolbar

  1. Click the Microsoft Office Button, and then click Application Options to display the Options dialog box.

  2. Click Popular.

  3. Clear the Show Mini Toolbar on selection option.

My Microsoft Office Access 2003 solution hides all Access menus and toolbars and displays custom menus and toolbars. What happens when users open this solution in Access 2007? Will my custom menus and toolbars appear on the Add-Ins tab?

Access 2007 can detect when an Access 2003 application includes settings to hide menus and toolbars, and to display only custom menus and toolbars. In this case, Access 2007 does not display the custom menus and toolbars on the Add-Ins tab.

How does attached Fluent UI customization XML work in Access 2007? Can I store the custom UI in the database? If so, how?

Because Access databases do not implement the new Office Open XML Formats file structure, Microsoft Visual Basic for Applications (VBA) solutions in Access usually store their markup in a table in the database. Create a table named USysRibbons and store two columns (RibbonName, a 255-character field, and RibbonXml, a memo field) that contain names and markup. You can then select a Ribbon by name from the table, by using the Options dialog box. You can also use standard data manipulation techniques to read XML content from a table, and call the Application.LoadCustomUI method to apply the new Ribbon content. You can find more information on the Office Fluent User Interface Developer Portal Web site.

What happens when two add-ins try to repurpose the same built-in control?

The last add-in that attempts to repurpose the control becomes the active add-in.

Can I programmatically remove items from built-in galleries?

You cannot programmatically remove items from built-in galleries by using extensibility. You may be able to remove them by using the application's object model.

Can I programmatically customize the Quick Access Toolbar, at least in a start-from-scratch scenario?

Yes. You can customize the Quick Access Toolbar by setting the startFromScratch attribute of the Ribbon element to true. However, we recommend not customizing the Quick Access Toolbar unless there is a good business reason—this feature is really meant for user customization.

How do I localize my UI?

You have two options. If you use COM, you can return different XML files, based on the current UI language. If you use VBA, you can have multiple VBA files for each language, or you can have a callback that returns the appropriate label for all of your controls.

Can I remove the Microsoft Office Button?

You can disable or hide all of the items on the Microsoft Office Button menu, but you cannot remove the button itself.

How do I write a VBA add-in that uses the Fluent UI, but that uses command bars in Office 2003 applications?

You can create one VBA document that uses the functionality of both Office 2003 and the 2007 Microsoft Office system. One way to do this is to check the version of Office, by using the Application.Version property. If the value is less than "12" (for 2007 Office applications), run your command bars code. Your Fluent UI XML markup is ignored by the converter that enables a document created in a 2007 Office application to be opened in an Office 2003 application. If the value is "12", you do not need to do any special processing. The file that contains your Fluent UI XML markup is loaded from the Office Open XML Formats file, and your callbacks are made available.

I cannot use extensibility to control the status bar. How do I programmatically hide the status bar?

You can hide the status bar by using the following line of code.

Application.CommandBars("Status Bar").Visible = False

How do I create two add-ins that add items to the same group or tab?

The idQ property of controls exists to enable multiple add-ins to share containers, such as custom tabs and groups.

In the following VBA example, two Excel add-ins share the same "Contoso" group on the add-ins tab; each adds one button to it. The key is specifying the same unique namespace in the <customUI> tag. Then, controls can reference this namespace by using idQ.

CustomUI for add-in 1

<customUI xmlns="http://schemas.microsoft.com/office/2006/01/customui" 
  xmlns:x="myNameSpace" >
  <ribbon>
    <tabs>
      <tab idMso="TabAddIns">
        <group idQ="x:Contoso" label="Contoso">
          <button id="C1" label="Contoso Button 1" size="large" 
            imageMso="FileSave" onAction="c_action1" />
        </group>
      </tab>
    </tabs>
  </ribbon>
</customUI>

CustomUI for add-in 2

<customUI xmlns="http://schemas.microsoft.com/office/2006/01/customui" 
  xmlns:x="myNameSpace" >
  <ribbon>
    <tabs>
      <tab idMso="TabAddIns">
        <group idQ="x:Contoso" label="Contoso">
          <button id="C2" label="Contoso Button 2" size="large" 
            imageMso="FileSave" onAction="c_action2" />
        </group>
      </tab>
    </tabs>
  </ribbon>
</customUI>

If you use a COM add-in to customize the Fluent UI, the namespace name must be the ProgID of the COM add-in, but the behavior is otherwise the same. When you use a shared add-in, the ProgID is AddInName.Connect. When you use Microsoft Visual Studio 2005 Tools for the 2007 Microsoft Office System (Visual Studio 2005 Tools for Office Second Edition) to create the add-in, the ProgID is the name of the add-in.

How can I assign KeyTips to my controls?

KeyTips are the keyboard shortcuts that appear on the Ribbon when you press the ALT key. You can assign your own KeyTips by using the keytip and getKeytip attributes. (The getKeytip attribute supplies the name of a callback procedure that provides the KeyTip.)

NoteNote

If your KeyTips conflict with built-in controls or KeyTips from other add-ins, they might be assigned non-conflicting values automatically. KeyTips for groups, as a rule, should start with the letter "Z".

(VBA only) If two documents have the same callback signatures, the callbacks from the active document are called. How do I ensure my UI calls only the callbacks associated with my document?

This is an issue that was also present in Office 2003. As a workaround, you can make your callback names unique by adding your add-in or solution name to the callback name. You can also put your callbacks in a module, and then refer to your callbacks by using the full name of the procedure. For example, if you put your callbacks in a module named "MyAddInXYZ", you can refer to the callbacks by using "MyAddInXYZ.myCallback".

Can I interact with Fluent UI controls from VBA?

The Application.CommandBars class provides the following methods for interacting with Fluent UI controls.

Table 2. Methods for the Application.CommandBars class

Method

Description

Sub ExecuteMso(idMso As String)

Executes the command that is specified in idMso.

Function GetImageMso(idMso As String, Width As Long, Height As Long) As IPictureDisp

Returns the image of the command specified in idMso, resized to the dimensions specified in Width and Height. (This works only in-process, similar to picture and mask in Office 2003.)

Function GetLabelMso(idMso As String) As String

Function GetLabelMso(idMso As String) As String

Function GetLabelMso(idMso As String) As String

Returns the requested control property as a String.

Function GetEnabledMso(idMso as String) as Boolean

Function GetEnabledMso(idMso as String) as Boolean

Function GetVisibleMso(idMso as String) as Boolean

Returns the state of built-in controls as a Boolean value.

How can I determine the Ribbon ID for Ribbons in the various applications?

The following table lists the Ribbon IDs for the different applications. Each application passes this ID to your solution in the getCustomUI method of the IRibbonExtensibility interface. This enables your application (or add-in) to determine which application has loaded your code, and you can return a different set of XML content depending on the identity of the host application.

Table 3. Ribbon IDs by application

Application

Ribbon ID

Access

Microsoft.Access.Database

Excel

Microsoft.Excel.Workbook

PowerPoint

Microsoft.PowerPoint.Presentation

Word

Microsoft.Word.Document

Outlook

Microsoft.Word.Document

Microsoft.Outlook.Mail.Read

Microsoft.Outlook.Mail.Compose

Microsoft.Outlook.MeetingRequest.Read

Microsoft.Outlook.MeetingRequest.Send

Microsoft.Outlook.Appointment

Microsoft.Outlook.Contact

Microsoft.Outlook.Journal

Microsoft.Outlook.Task

Microsoft.Outlook.DistributionList

Microsoft.Outlook.Report

Microsoft.Outlook.Resend

Microsoft.Outlook.Response.Read

Microsoft.Outlook.Response.Compose

Microsoft.Outlook.Response.CounterPropose

Microsoft.Outlook.RSS

Microsoft.Outlook.Post.Read

Microsoft.Outlook.Post.Compose

Microsoft.Outlook.DistributionList

Microsoft.Outlook.Report

Microsoft.Outlook.Resend

Microsoft.Outlook.Response.Read

Microsoft.Outlook.Response.Compose

Microsoft.Outlook.Response.CounterPropose

Microsoft.Outlook.Response.CounterPropose

Microsoft.Outlook.RSS

Microsoft.Outlook.Post.Read

Microsoft.Outlook.Post.Compose

Microsoft.Outlook.Sharing.Read

Microsoft.Outlook.Sharing.Compose

Can I add images to my Enhanced ScreenTips?

No. You can add only text, by using the Supertip property.

How do I start a new line in an Enhanced ScreenTip?

Type the following character code where you want the new line to start:

&#13;

How do I invalidate a control that has a qualified ID (idQ)?

You can call a callback procedure and pass the ID of the control in the following way.

Assume that idQ="x:test_idq"

You invoke the callback by using the following method.

InvalidateControl("test_idq")

NoteNote

If you customize the Fluent UI by using a COM add-in, the x namespace in the example must be set to the ProgID of the add-in that contains the callback procedure. Otherwise, the callbacks and InvalidateControl do not work, because the callback does not know which add-in to call.

You cannot set callbacks or invalidate controls from a different add-in (even though they are specified by using the idQ attribute in the current add-in's XML). Only the add-in that has the ProgID namespace gets callbacks and can invalidate the control.

How do I write a shim for my COM add-in?

See the information in the MSDN article Isolating Office Extensions with the COM Shim Wizard.

How do I display large menu items?

In the <menu> tag in the Fluent UI XML file, set itemSize="large". For any element that supports the itemSize attribute, set the value to large to cause the item to appear large (set the value to normal for normal-sized items).

Can I have two callbacks with the same name but different signatures?

Although you can do this, we recommended that you have different callbacks for each control (and not count on built-in overloading to handle the distinction between the two callbacks). For example, assume that you write a Fluent UI add-in with two callbacks of the same name, as in the following code.

public void doSomething(IRibbonControl control, bool pressState);
public void doSomething(IRibbonControl control);

Also assume that your XML markup defines a toggleButton control and a button control, and that each of them has an onAction="doSomething" callback.

In this instance, only the toggleButton control will work, because of the Visual Basic and Visual C# auto-generated IDispatch implementation. If you write a C++ add-in and implement IDispatch yourself, this case will work. (In other words, it is best not to do this.)

How can I determine the correct signatures for each callback procedure?

The following table lists all of the callbacks, along with their procedure signatures for C++, VBA, C#, and Visual Basic.

Table 4. List of all C#, VBA, C++, and Visual Basic callbacks and signatures

Control

Callback Name

Signatures

(several controls)

getDescription

C#: string GetDescription(IRibbonControl control)

VBA: Sub GetDescription(control As IRibbonControl, ByRef description)

C++: HRESULT GetDescription([in] IRibbonControl *pControl, [out, retval] BSTR *pbstr Description)

Visual Basic: Function GetDescription(control As IRibbonControl) As String

(several controls)

getEnabled

C#: bool GetEnabled(IRibbonControl control)

VBA: Sub GetEnabled(control As IRibbonControl, ByRef enabled)

C++: HRESULT GetEnabled([in] IRibbonControl *pControl, [out, retval] VARIANT_BOOL *pvarfEnabled)

Visual Basic: Function GetEnabled(control as IRibbonControl) As Boolean

(several controls)

getImage

C#: IPictureDisp GetImage(IRibbonControl control)

VBA: Sub GetImage(control As IRibbonControl, ByRef image)

C++: HRESULT GetImage([in] IRibbonControl *pControl, [out, retval] IPictureDisp ** ppdispImage)

Visual Basic: Function GetImage(control as IRibbonControl) as IPictureDisp

(several controls)

getImageMso

C#: string GetImageMso(IRibbonControl control)

VBA: Sub GetImageMso(control As IRibbonControl, ByRef imageMso)

C++: HRESULT GetImageMso([in] IRibbonControl *pControl, [out, retval] BSTR *pbstrImageMso)

Visual Basic: Function GetImageMso(control as IRibbonControl) as String

(several controls)

getLabel

C#: string GetLabel(IRibbonControl control)

VBA: Sub GetLabel(control As IRibbonControl, ByRef label)

C++: HRESULT GetLabel([in] IRibbonControl *pControl, [out, retval] BSTR *pbstrLabel)

Visual Basic: Function GetLabel(control As IRibbonControl) As String

(several controls)

getKeytip

C#: string GetKeytip(IRibbonControl control)

VBA: Sub GetKeytip (control As IRibbonControl, ByRef label)

C++: HRESULT GetKeytip ([in] IRibbonControl *pControl, [out, retval] BSTR *pbstrKeytip)

Visual Basic: Function GetKeytip (control As IRibbonControl) As String

(several controls)

getSize

C#: RibbonControlSize GetSize(IRibbonControl control)

VBA: sub GetSize(control As IRibbonControl, ByRef size)

C++: HRESULT GetSize([in] IRibbonControl *pControl, [out, retval] RibbonControlSize *pintSize)

Visual Basic: Function GetSize(control As IRibbonControl) As RibbonControlSize

(several controls)

getScreentip

C#: string GetScreentip(IRibbonControl control)

VBA: Sub GetScreentip(control As IRibbonControl, ByRef screentip)

C++: HRESULT GetScreentip([in] IRibbonControl *pControl, [out, retval] BSTR *pbstrScreentip)

Visual Basic: Function GetScreentip(control As IRibbonControl) As String

(several controls)

getSupertip

C#: string GetSupertip(IRibbonControl control)

VBA: Sub GetSupertip(control As IRibbonControl, ByRef screentip)

C++: HRESULT GetSupertip([in] IRibbonControl *pControl, [out, retval] BSTR *pbstrScreentip)

Visual Basic: Function GetSupertip(control As IRibbonControl) As String

(several controls)

getVisible

C#: bool GetVisible(IRibbonControl control)

VBA: Sub GetVisible(control As IRibbonControl, ByRef visible)

C++: HRESULT GetVisible([in] IRibbonControl *pControl, [out, retval] VARIANT_BOOL *pvarfVisible)

Visual Basic: Function GetVisible(control As IRibbonControl) As Boolean

button

getShowImage

C#: bool GetShowImage(IRibbonControl control)

VBA: Sub GetShowImage (control As IRibbonControl, ByRef showImage)

C++: HRESULT GetShowImage ([in] IRibbonControl *pControl, [out, retval] VARIANT_BOOL *pvarShowImage)

Visual Basic: Function GetShowImage (control As IRibbonControl) As Boolean

button

getShowLabel

C#: bool GetShowLabel(IRibbonControl control)

VBA: Sub GetShowLabel (control As IRibbonControl, ByRef showLabel)

C++: HRESULT GetShowLabel ([in] IRibbonControl *pControl, [out, retval] VARIANT_BOOL *pvarShowLabel)

Visual Basic: Function GetShowLabel (control As IRibbonControl) As Boolean

button

onAction – repurposed

C#: void OnAction(IRibbonControl control, ref bool CancelDefault)

VBA: Sub OnAction(control As IRibbonControl, byRef CancelDefault)

C++: HRESULT OnAction([in] IRibbonControl *pControl, [in,out] VARIANT _BOOL *fCancelDefault)

Visual Basic: Sub OnAction(control As IRibbonControl, byRef CancelDefault)

button

onAction

C#: void OnAction(IRibbonControl control)

VBA: Sub OnAction(control As IRibbonControl)

C++: HRESULT OnAction([in] IRibbonControl *pControl)

Visual Basic: Sub OnAction(control As IRibbonControl)

checkBox

getPressed

C#: bool GetPressed(IRibbonControl control)

VBA: Sub GetPressed(control As IRibbonControl, ByRef returnValue)

C++: HRESULT GetPressed([in] IRibbonControl *pControl, [out, retval] VARIANT_BOOL *pvarfPressed)

Visual Basic: Function GetPressed(control As IRibbonControl) As Boolean

checkBox

onAction

C#: void OnAction(IRibbonControl control, bool pressed)

VBA: Sub OnAction(control As IRibbonControl, pressed As Boolean)

C++: HRESULT OnAction([in] IRibbonControl *pControl, [in] VARIANT_BOOL *pvarfPressed)

Visual Basic: Sub OnAction(control As IRibbonControl, pressed As Boolean)

comboBox

getItemCount

C#: int GetItemCount(IRibbonControl control)

VBA: Sub GetItemCount(control As IRibbonControl, ByRef count)

C++: HRESULT GetItemCount([in] IRibbonControl *pControl, [out, retval] long *count)

Visual Basic: Function GetItemCount(control As IRibbonControl) As Integer

comboBox

getItemID

C#: string GetItemID(IRibbonControl control, int index)

VBA: Sub GetItemID(control As IRibbonControl, index As Integer, ByRef id)

C++: HRESULT GetItemID([in] IRibbonControl *pControl, [in] long cIndex, [out, retval] BSTR *pbstrID)

Visual Basic: Function GetItemID(control As IRibbonControl, index As Integer) As String

comboBox

getItemImage

C#: IPictureDisp GetItemImage(IRibbonControl control, int index)

VBA: Sub GetItemImage(control As IRibbonControl, index As Integer, ByRef image)

C++: HRESULT GetItemImage([in] IRibbonControl *pControl, [in] long cIndex, [out, retval] IPictureDisp **ppdispImage)

Visual Basic: Function GetItemImage(control As IRibbonControl, index As Integer) As IPictureDisp

comboBox

getItemLabel

C#: string GetItemLabel(IRibbonControl control, int index)

VBA: Sub GetItemLabel(control As IRibbonControl, index As Integer, ByRef label)

C++: HRESULT GetItemLabel([in] IRibbonControl *pControl, [in] long cIndex, [out, retval] BSTR *pbstrLabel)

Visual Basic: Function GetItemLabel(control As IRibbonControl, index As Integer) As String

comboBox

getItemScreenTip

C#: string GetItemScreenTip(IRibbonControl control, int index)

VBA: Sub GetItemScreenTip(control As IRibbonControl, index As Integer, ByRef screentip)

C++: HRESULT GetItemScreentip([in] IRibbonControl *pControl, [in] long cIndex, [out, retval] BSTR *pbstrScreentip)

Visual Basic: Function GetItemScreentip(control As IRibbonControl, index As Integer) As String

comboBox

getItemSuperTip

C#: string GetItemSuperTip(IRibbonControl control, int index)

VBA: Sub GetItemSuperTip (control As IRibbonControl, index As Integer, ByRef supertip)

C++: HRESULT GetItemSuperTip ([in] IRibbonControl *pControl, [in] long cIndex, [out, retval] BSTR *pbstrScreentip)

Visual Basic: Function GetItemSuperTip (control As IRibbonControl, index As Integer) As String

comboBox

getText

C#: string GetText(IRibbonControl control)

VBA: Sub GetText(control As IRibbonControl, ByRef text)

C++: HRESULT GetText([in] IRibbonControl *pControl, [out, reval] BSTR *pbstrText)

Visual Basic: Function GetText(control As IRibbonControl) As String

comboBox

onChange

C#: void OnChange(IRibbonControl control, string text)

VBA: Sub OnChange(control As IRibbonControl, text As String)

C++: HRESULT OnChange([in] IRibbonControl *pControl, [in] BSTR *pbstrText)

Visual Basic: Sub OnChange(control As IRibbonControl, text As String)

customUI

loadImage

C#: IPictureDisp LoadImage(string image_id)

VBA: Sub LoadImage(imageId As string, ByRef image)

C++: HRESULT LoadImage([in] BSTR *pbstrImageId, [out, retval] IPictureDisp ** ppdispImage)

Visual Basic: Function LoadImage(imageId As String) As IPictureDisp

customUI

onLoad

C#: void OnLoad(IRibbonUI ribbon)

VBA: Sub OnLoad(ribbon As IRibbonUI)

C++: HRESULT OnLoad([in] IRibbonUI *pRibbon)

Visual Basic: Function OnLoad(ribbon As IRibbonUI)

dropDown

getItemCount

C#: int GetItemCount(IRibbonControl control)

VBA: Sub GetItemCount(control As IRibbonControl, ByRef count)

C++: HRESULT GetItemCount([in] IRibbonControl *pControl, [out, retval] long *count)

Visual Basic: Function GetItemCount(control As IRibbonControl) As Integer

dropDown

getItemID

C#: string GetItemID(IRibbonControl control, int index)

VBA: Sub GetItemID(control As IRibbonControl, index As Integer, ByRef id)

C++: HRESULT GetItemID([in] IRibbonControl *pControl, [in] long cIndex, [out, retval] BSTR *pbstrID)

Visual Basic: Function GetItemID(control As IRibbonControl, index As Integer) As String

dropDown

getItemImage

C#: IPictureDisp GetItemImage(IRibbonControl control, int index)

VBA: Sub GetItemImage(control As IRibbonControl, index As Integer, ByRef image)

C++: HRESULT GetItemImage([in] IRibbonControl *pControl, [in] long cIndex, [out, retval] IPictureDisp **ppdispImage)

Visual Basic: Function GetItemImage(control As IRibbonControl, index As Integer) As IPictureDisp

dropDown

getItemLabel

C#: string GetItemLabel(IRibbonControl control, int index)

VBA: Sub GetItemLabel(control As IRibbonControl, index As Integer, ByRef label)

C++: HRESULT GetItemLabel([in] IRibbonControl *pControl, [in] long cIndex, [out, retval] BSTR *pbstrLabel)

Visual Basic: Function GetItemLabel(control As IRibbonControl, index As Integer) As String

dropDown

getItemScreenTip

C#: string GetItemScreenTip(IRibbonControl control, int index)

VBA: Sub GetItemScreenTip(control As IRibbonControl, index As Integer, ByRef screenTip)

C++: HRESULT GetItemScreentip([in] IRibbonControl *pControl, [in] long cIndex, [out, retval] BSTR *pbstrScreentip)

Visual Basic: Function GetItemScreentip(control As IRibbonControl, index As Integer) As String

dropDown

getItemSuperTip

C#: string GetItemSuperTip(IRibbonControl control, int index)

VBA: Sub GetItemSuperTip (control As IRibbonControl, index As Integer, ByRef superTip)

C++: HRESULT GetItemSuperTip ([in] IRibbonControl *pControl, [in] long cIndex, [out, retval] BSTR *pbstrSupertip)

Visual Basic: Function GetItemSuperTip (control As IRibbonControl, index As Integer) As String

dropDown

getSelectedItemID

C#: string GetSelectedItemID(IRibbonControl control)

VBA: Sub GetSelectedItemID(control As IRibbonControl, ByRef index)

C++: HRESULT GetSelectedItemID([in] IRibbonControl *pControl, [out, retval] LONG *pcItemIndex)

Visual Basic: Function GetSelectedItemID(control As IRibbonControl) As Integer

dropDown

getSelectedItemIndex

C#: int GetSelectedItemIndex(IRibbonControl control)

VBA: Sub GetSelectedItemIndex(control As IRibbonControl, ByRef index)

C++: HRESULT GetSelectedItemIndex([in] IRibbonControl *pControl, [out, retval] LONG *pcItemIndex)

Visual Basic: Function GetSelectedItemIndex(control As IRibbonControl) As Integer

dropDown

onAction

C#: void OnAction(IRibbonControl control, string selectedId, int selectedIndex)

VBA: Sub OnAction(control As IRibbonControl, selectedId As String, selectedIndex As Integer)

C++: HRESULT OnAction([in] IRibbonControl *pControl, [in] BSTR *selectedId, [in] LONG cSelectedIndex)

Visual Basic: Sub OnAction(control As IRibbonControl, selectedId As String, selectedIndex As Integer)

dynamicMenu

getContent

C#: string GetContent(IRibbonControl control)

VBA: Sub GetContent(control As IRibbonControl, ByRef content)

C++: HRESULT GetContent([in] IRibbonControl *pControl, [out, retval] BSTR *pbstrContent)

Visual Basic: Function GetContent(control As IRibbonControl) As String

editBox

getText

C#: string GetText(IRibbonControl control)

VBA: Sub GetText(control As IRibbonControl, ByRef text)

C++: HRESULT GetText([in] IRibbonControl *pControl, [out, retval] BSTR *pbstrText)

Visual Basic: Function GetText(control As IRibbonControl) As String

editBox

onChange

C#: void OnChange(IRibbonControl control, string text)

VBA: Sub OnChange(control As IRibbonControl, text As String)

C++: HRESULT OnChange([in] IRibbonControl *pControl, [in] BSTR *pbstrText)

Visual Basic: Sub OnChange(control As IRibbonControl, text As String)

gallery

getItemCount

C#: int GetItemCount(IRibbonControl control)

VBA: Sub GetItemCount(control As IRibbonControl, ByRef count)

C++: HRESULT GetItemCount([in] IRibbonControl *pControl, [out, retval] long *count)

Visual Basic: Function GetItemCount(control As IRibbonControl) As Integer

gallery

getItemHeight

C#: int getItemHeight(IRibbonControl control)

VBA: Sub getItemHeight(control As IRibbonControl, ByRef height)

C++: HRESULT getItemHeight([in] IRibbonControl *pControl, [out, retval] LONG *height)

Visual Basic: Function getItemHeight(control As IRibbonControl) As Integer

gallery

getItemID

C#: string GetItemID(IRibbonControl control, int index)

VBA: Sub GetItemID(control As IRibbonControl, index As Integer, ByRef id)

C++: HRESULT GetItemID([in] IRibbonControl *pControl, [in] long cIndex, [out, retval] BSTR *pbstrID)

Visual Basic: Function GetItemID(control As IRibbonControl, index As Integer) As String

gallery

getItemImage

C#: IPictureDisp GetItemImage(IRibbonControl control, int index)

VBA: Sub GetItemImage(control As IRibbonControl, index As Integer, ByRef image)

C++: HRESULT GetItemImage([in] IRibbonControl *pControl, [in] long cIndex, [out, retval] IPictureDisp **ppdispImage)

Visual Basic: Function GetItemImage(control As IRibbonControl, index As Integer) As IPictureDisp

gallery

getItemLabel

C#: string GetItemLabel(IRibbonControl control, int index)

VBA: Sub GetItemLabel(control As IRibbonControl, index As Integer, ByRef label)

C++: HRESULT GetItemLabel([in] IRibbonControl *pControl, [in] long cIndex, [out, retval] BSTR *pbstrLabel)

Visual Basic: Function GetItemLabel(control As IRibbonControl, index As Integer) As String

gallery

getItemScreenTip

C#: string GetItemScreenTip(IRibbonControl control, int index)

VBA: Sub GetItemScreenTip(control As IRibbonControl, index as Integer, ByRef screen)

C++: HRESULT GetItemScreentip([in] IRibbonControl *pControl, [in] long cIndex, [out, retval] BSTR *pbstrScreentip)

Visual Basic: Function GetItemScreentip(control As IRibbonControl, index As Integer) As String

gallery

getItemSuperTip

C#: string GetItemSuperTip(IRibbonControl control, int index)

VBA: Sub GetItemSuperTip (control As IRibbonControl, index as Integer, ByRef screen)

C++: HRESULT GetItemSuperTip ([in] IRibbonControl *pControl, [in] long cIndex, [out, retval] BSTR *pbstrSupertip)

Visual Basic: Function GetItemSuperTip (control As IRibbonControl, index As Integer) As String

gallery

getItemWidth

C#: int getItemWidth(IRibbonControl control)

VBA: Sub getItemWidth(control As IRibbonControl, ByRef width)

C++: HRESULT getItemWidth([in] IRibbonControl *pControl, [out, retval] LONG *width)

Visual Basic: Function getItemWidth(control As IRibbonControl) As Integer

gallery

getSelectedItemID

C#: int GetSelectedItemID(IRibbonControl control)

VBA: Sub GetSelectedItemID(control As IRibbonControl, ByRef index)

C++: HRESULT GetSelectedItemID([in] IRibbonControl *pControl, [out, retval] LONG *pcItemIndex)

Visual Basic: Function GetSelectedItemID(control As IRibbonControl) As Integer

gallery

getSelectedItemIndex

C#: int GetSelectedItemIndex(IRibbonControl control)

VBA: Sub GetSelectedItemIndex(control As IRibbonControl, ByRef index)

C++: HRESULT GetSelectedItemIndex([in] IRibbonControl *pControl, [out, retval] LONG *pcItemIndex)

Visual Basic: Function GetSelectedItemIndex(control As IRibbonControl) As Integer

gallery

onAction

C#: void OnAction(IRibbonControl control, string selectedId, int selectedIndex)

VBA: Sub OnAction(control As IRibbonControl, selectedId As String, selectedIndex As Integer)

C++: HRESULT OnAction([in] IRibbonControl *pControl, [in] BSTR *selectedId, [in] LONG cSelectedIndex)

Visual Basic: Sub OnAction(control As IRibbonControl, selectedId As String, selectedIndex As Integer)

menuSeparator

getTitle

C#: string GetTitle(IRibbonControl control)

VBA: Sub GetTitle (control As IRibbonControl, ByRef title)

C++: HRESULT GetTitle ([in] IRibbonControl *pControl, [out, retval] BSTR *pbstrTitle)

Visual Basic: Function GetTitle (control As IRibbonControl) As String

toggleButton

getPressed

C#: bool GetPressed(IRibbonControl control)

VBA: Sub GetPressed(control As IRibbonControl, ByRef returnValue)

C++: HRESULT GetPressed([in] IRibbonControl *pControl, [out, retval] VARIANT_BOOL *pvarfPressed)

Visual Basic: Function GetPressed(control As IRibbonControl) As Boolean

toggleButton

onAction - repurposed

C#: void OnAction(IRibbonControl control, bool pressed, ref bool cancelDefault)

VBA: Sub OnAction(control As IRibbonControl, pressed As Boolean, byRef cancelDefault)

C++: HRESULT OnAction([in] IRibbonControl *pControl, [in] VARIANT_BOOL *pvarfPressed, [in,out] VARIANT _BOOL *fCancelDefault)

Visual Basic: Sub OnAction(control As IRibbonControl, pressed As Boolean, byRef CancelDefault)

toggleButton

onAction

C#: void OnAction(IRibbonControl control, bool pressed)

VBA: Sub OnAction(control As IRibbonControl, pressed As Boolean)

C++: HRESULT OnAction([in] IRibbonControl *pControl, [in] VARIANT_BOOL *pvarfPressed)

Visual Basic: Sub OnAction(control As IRibbonControl, pressed As Boolean)

How do I find out what each Ribbon attribute indicates?

The following table lists all of the Ribbon attributes and includes a short description of each.

Table 5. Ribbon attributes

Attribute

Type or value

Description

description

String

Specifies description text that is displayed in menus when the itemSize attribute is set to large.

enabled

true, false, 0, 1

Specifies whether the control is enabled.

getContent

callback

For a dynamic menu, retrieves XML content that describes the menu.

getDescription

callback

Gets the description of a control.

getEnabled

callback

Gets the enabled state of a control.

getImage

callback

Gets the image for this control.

getImageMso

callback

Gets a built-in control's icon by using the control ID.

getItemCount

callback

For a combo box, drop-down list, or gallery, gets the number of items to be displayed.

getItemID

callback

For a combo box, drop-down list, or gallery, gets the ID for a specific item.

getItemImage

callback

For a combo box, drop-down list, or gallery, gets the image for a specific item.

getItemLabel

callback

For a combo box, drop-down list, or gallery, gets the label for a specific item.

getItemScreentip

callback

For a combo box, drop-down list, or gallery, gets the ScreenTip for a specific item.

getItemSupertip

callback

For a combo box, drop-down list, or gallery, gets the Enhanced ScreenTip for a specific item.

getKeytip

callback

Gets the KeyTip for a control.

getLabel

callback

Gets the label for a control.

getPressed

callback

For a toggle button, gets a value that indicates whether the state is pressed or not pressed.

For a check box, gets a value that indicates whether the state is selected or cleared.

getScreentip

callback

Gets the ScreenTip for a control.

getSelectedItemID

callback

For a drop-down list or gallery, gets the ID of the selected item.

getSelectedItemIndex

callback

For a drop-down list or gallery, gets the index of the selected item.

getShowImage

callback

Gets a value that specifies whether to display the control image.

getShowLabel

callback

Gets a value that specifies whether to display the control label.

getSize

callback

Gets a value that specifies the size of a control (normal or large).

getSupertip

callback

Gets a value that specifies the Enhanced ScreenTip for a control.

getText

callback

For a text box or edit box, gets the text to be displayed in the edit portion of the control.

getTitle

callback

For a menu separator, gets the text to be displayed (rather than a horizontal line).

getVisible

callback

Gets a value that specifies whether the control is visible.

id

String

A user-defined unique identifier for the control (mutually exclusive with idMso and idQ—specify only one of these values).

idMso

control id

Built-in control ID (mutually exclusive with id and idQ—specify only one of these values).

idQ

qualified id

Qualified control ID, prefixed with a namespace identifier (mutually exclusive with id and idMso—specify only one of these values).

image

String

Specifies an image for the control. (In VBA, this value is a relationship ID.)

imageMso

control id

Specifies an identifier for a built-in image, so that the Fluent UI copies the control's icon.

insertAfterMso

control id

Specifies the identifier for the built-in control after which to position this control.

insertAfterQ

qualified id

Specifies the identifier of a qualified control (that is, a control whose idQ property was specified) after which to position this control.

insertBeforeMso

control id

Specifies the identifier for the built-in control before which to position this control.

insertBeforeQ

qualified id

Specifies the identifier of a qualified control (that is, a control whose idQ property was specified) before which to position this control.

itemSize

large, normal

For a menu, specifies the size for the items in the menu.

keytip

String

Specifies the KeyTip for this control. The KeyTip is displayed when the user presses the ALT key plus one to three letters.

label

String

Specifies the label for the control.

onAction

callback

Called when the user clicks this control.

onChange

callback

Called when the user commits text in an edit box or combo box.

screentip

String

Specifies the control's ScreenTip.

showImage

true, false, 0, 1

Specifies whether to display the control's image.

showItemImage

true, false, 0, 1

In a combo box, drop-down list, or gallery, specifies whether to show each item's image.

showItemLabel

true, false, 0, 1

In a combo box, drop-down list, or gallery, specifies whether to show each item's label.

showLabel

true, false, 0, 1

Specifies whether to show the control's label.

size

large, normal

Specifies the size for this control.

sizeString

String

Specifies a string, such as "MMMMM", that indicates the width for the control.

supertip

String

Specifies the Enhanced ScreenTip for the control (generally, a longer and more complete version of the ScreenTip).

tag

String

Specifies user-defined text that enables you to store information about the control that is not pertinent to any other specific property.

title

String

For a menu separator, specifies the text to be displayed (rather than a horizontal line).

visible

true, false, 0, 1

Specifies whether the control is visible.

I am looking for guidance about how to create a consistent end-user experience when customizing the Fluent UI directly with XML files or through add-ins. Can you help?

You can find the 2007 Office system guidance document UI Style Guide for Solutions and Add-Ins on the Microsoft Download Center.

Is it possible to line up (either right-justify or left-justify) text boxes in my custom Fluent UI?

No. However, you might be able to get a similar effect by using the box control. The box control is a container for other controls that has a boxStyle attribute that can be set to horizontal or vertical.

I have a document that I created from a template containing several macros. I have tried calling the macros from the Ribbon onAction callbacks without success. How can I call existing macros from Ribbon controls without modifying the original macros?

It is not possible to call macros that were created for an earlier version of Office directly from a Ribbon control without modifying the macros to include a reference to the control. However, there is a workaround. You can create a new module that contains a macro that hosts all of the Ribbon callbacks. When a call is made to the new macro from a Ribbon control, the older macro is called. The following code shows an example.

New Ribbon extensibility module

Sub RibbonX_macroname(control as IRibbonControl)
   Select Case control 
      button1
         macroname1
      button2
         macroname2
   End Select
End Sub

How do I get the selected index or item ID for a combo box control?

The onChange callback returns the selected string. The following code shows the signature.

Sub OnChange(control as IRibbonControl, text as String)

Whenever the value of the combo box is selected, the onChange callback receives the text. However, it is not possible to get the index of the selection.

Is it possible to predict or control the order in which callbacks are called?

No. You should not add logic to your Fluent UI solutions that depends on callbacks being called in a certain order.

In an application that uses command-bar controls, the Tag property was useful for storing arbitrary strings. How can I use the IRibbonControl.Tag property in my Fluent UI solutions?

The 2007 Microsoft Office applications do not use the Tag property, so you can use it to store arbitrary strings and then retrieve them at run time. In your XML, you can set the tag as in the following code.

<button id="mybutton" tag="some string" onAction="MyFunction"/>

When MyFunction is called, you can get the IRibbonControl.Tag property, which will be "some string".

Normally, you can distinguish between your controls by using the IRibbonControl.Id property, but there are restrictions on what IDs can contain (no non-alphanumeric characters, and they must all be unique). The Tag property does not have these restrictions, so it can be used in the following situations, where the Id property does not work:

  • If you need to store a special string with your control, such as a file name, as in this example: tag="C:\path\to\my\file.xlsm"

  • If you want multiple controls to be treated the same way by your callbacks, but you do not want to have a list of all of their IDs (which have to be unique). For example, you could have buttons on different tabs all with tag="blue", and then just check the Tag property instead of the ID for some action in the callback.

Is it possible to display an image in a ScreenTip or Enhanced ScreenTip similar to the Chart button in the Illustrations group on the Insert tab?

No. This is not currently supported in Fluent UI extensibility.

Assume I have a custom Ribbon defined for Outlook 2007 and a different Ribbon defined for Word 2007. If I use Word for my e-mail editor, which Ribbon will I see when I create or edit an e-mail message?

When a new Inspector type is created, Outlook will call the GetCustomUI method and pass in the Ribbon ID as an argument. Even though Outlook uses Word APIs, it is still an Outlook container and uses the Outlook Ribbon.

Conclusion

The articles that make up this set provide you with the information that you need to produce professional-looking solutions that are tailored to the needs of your customers. The customization samples presented in Customizing the 2007 Office Fluent Ribbon for Developers (Part 1 of 3) can be used as a jumping-off point for creating a UI that places the controls and options that are most important to your customers within easy reach. The reference information described in Customizing the 2007 Office Fluent Ribbon for Developers (Part 2 of 3) gives you detailed control over the look and feel of the Fluent UI. This article answers many of the questions that might arise as you create your own customized Fluent UI. By applying the information presented in these articles to your own applications, you can create more innovative, attractive solutions that set you apart from your competition.

Additional Resources

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