Introduction

The Ribbon was originally designed by the Office team to replace their applications' complex systems of menus
and toolbars. In Windows 7, Microsoft released a reusable COM-based Ribbon component for use in native Win32 applications.
The native Ribbon is slightly different from the other Ribbon components in Office, WPF, and MFC, but they all
share the same basic layout and functionality.

Because the Ribbon has lots of features, this first article will cover just the basics of the Ribbon and its
COM interfaces, and will demonstrate the steps required to create an app from scratch that uses a simple Ribbon.
If you want to dive right into Ribbon development, check out the other Ribbon articles here on CodeProject, or
the Ribbon classes in the forthcoming WTL 8.1.

The system requirements for building the sample code are Visual Studio 2008, WTL
8.0, and the Windows
7 SDK. If you are running Windows 7 or Server 2008 R2, you have everything you need. If you are using Vista
or Server 2008, you must install service pack 2 and the platform
update for your operating system to use the Ribbon.

Starting a New App

Prep work in CMainFrame

We'll start with a basic SDI app as created by the WTL AppWizard. This app does not have a toolbar (since the
Ribbon replaces the toolbar), but it does have a status bar. It uses a separate class for the view window, but
the view window won't do too much, since our focus is on getting the Ribbon up and running. Later on, we'll do
more with the view window when it comes to laying out the main frame's child controls.

The first step is to include UIRibbon.h, which contains the type and interface definitions we'll need
to use the Ribbon. Our app will implement two of those interfaces, and the implementation details are outlined
throughout the rest of the article. For starters, all we need to do is add IUIApplication to the inheritance
list of CMainFrame, then add stub implementations of the three methods:

Since CMainFrame needs to be a COM object, it also derives from CComObjectRootEx.
Also, the single CMainFrame instance in the Run() function is created using CComObjectStackEx,
in order to use ATL's implementation of IUnknown:

Initializing the UI Framework

The first interaction we have with the Ribbon is through the IUIFramework interface. CMainFrame
uses this interface to initialize and shut down the framework, so it needs to keep an interface pointer for the
lifetime of the app:

IUIFramework::Initialize() takes the HWND of the window that will contain the Ribbon,
and the IUIApplication interface that the framework will use to communicate with the app. The framework
changes the appearance of the window to fit in with the Ribbon's visual guidelines. For example, the framework
removes the window's menu and draws controls in the caption bar. To ensure that those features work smoothly, the
framework requires that the window be a top-level window with the WS_CAPTION style, and without the
WS_EX_TOOLWINDOW style. IUIFramework::Initialize() will return ERROR_INVALID_WINDOW_HANDLE
if the window does not meet those conditions.

In order to properly shut down the framework and release any resources it was using, we also need to call IUIFramework::Destroy()
in the WM_DESTROY handler:

After adding the call to IUIFramework::Initialize(), our frame window looks like this:

There is no Ribbon yet, of course, since we haven't defined the contents of our Ribbon, but the framework has
made the necessary visual tweaks like removing the menu.

Adding a Ribbon to the Application

The Ribbon works differently than other UI widgets that you've used before. One of the design principles is
that the definition of a Ribbon's contents should be separate from its visual design. An app can specify what commands
appear in the Ribbon, how they are organized and grouped, and so on. But the app has limited control over how the
Ribbon will actually look. This lets Microsoft change the Ribbon's appearance in the future with fewer compatibility
problems than existing ways of creating GUIs like dialog resources.

The steps in creating a Ribbon definition are:

Create an XML file that defines the Ribbon's contents and add that file to your project.

Compile the XML with the uicc tool.

Add the files that uicc generates to your app's resources.

Call IUIFramework::LoadUI() to create a Ribbon using the compiled definition.

Before we dive into the XML, we need to become familiar with the elements of the Ribbon.

Parts of the Ribbon

The Ribbon uses the notion of a command in many places. A command is more than a button, it's essentially
anything in the Ribbon that you can click and do things with. Commands have various properties, such as a text
label, an icon, and a shortcut key. Once you've made the list of commands in your app, you start building other
parts of the Ribbon out of those commands.

Here's a screen shot of the Paint window, showing the various parts of the Ribbon:

Application menu: The button to the left of the first tab opens the Application menu. This is a command
itself, although it does not allow its appearance to be customized. The menu contains other commands.

Quick access toolbar (QAT): The QAT is the toolbar that the Ribbon draws in the window's caption area.
You can add other commands to the toolbar by right-clicking them and selecting Add to Quick Access Toolbar
on the context menu. The down arrow at the right edge of the QAT shows a menu where you can customize the commands
in the toolbar and change the appearance of the QAT and the Ribbon.

Tabs: The tab row shows all the tabs that you've defined in the XML file. Each tab is a command, and
it contains one or more groups.

Groups: Each group is a collection of commands. A group has an optional label at the bottom, and the
Ribbon draws dividers between the groups. You might occasionally see the term chunk used instead of group.
This is not the official term, but it was used by the Office team when they were building the first Ribbon, and
it still gets used in unofficial written material like blog posts.

Notice that some properties are written using child tags with the "object.property" naming convention,
similar to XAML. For example, <Application.Commands> defines the Commands property
of the <Application> tag.

The first step is to create a few commands that we'll use in the <Ribbon> sections. Each
command is defined in a <Command> tag. <Command> has several properties that
we'll see later, but for now, we'll use two: Name and LabelTitle. The Name
property is a string that identifies the command in the rest of the XML file, and LabelTitle is a
string that sets the text of the UI element.

In order to create a button, we also need a group and a tab to put it in, so we start with three commands:

(The Microsoft samples I've seen use the "cmd" prefix in all command names, but I've chosen to use
more descriptive prefixes that indicate the function of each command.) Then we create a tab, a group, and a button
control in the group:

This creates a tab that contains one group. Most of the tab's properties come from the associated <Command>
tag. There's a level of indirection here: You don't say what the text of a tab is, you say what command
the tab is, and the Ribbon looks up the text in the associated <Command> tag. Similarly, the
group's label comes from the LabelTitle property of the grpHello command. Don't worry
about the SizeDefinition attribute for now, it's just something that's required so the Ribbon knows
how to arrange the controls in the group.

Finally, there's a <Button> tag that creates a regular push button. The separation of properties
into <Command> tags is more useful for buttons, since it's possible to have the same command
in multiple places, and having that separation means you don't have to repeat the same properties in every place
that the command appears.

Compiling the Ribbon XML file

Now that we've created the Ribbon definition file, we need to incorporate it into the app. If you've saved the
above XML to a file called ribbon.xml, you can add it to the Visual Studio project by clicking Project|Add
Existing Item and selecting ribbon.xml.

The next step is to invoke the compiler (uicc.exe) that converts the XML to a binary format that the Ribbon
understands. Open the properties for ribbon.xml, and in the Custom build step settings, set the Command
line field to:

ribbon.bml: The compiled output. Microsoft's samples use the .bml extension, and I've followed
suit.

ribbonids.h: A C header file that has #defines for all commands and strings that are defined
in the XML.

ribbon.rc: A resource definition file that has definitions for string and icons referenced in the XML,
and one custom resource type that pulls in ribbon.bml. The /name switch controls the name of
this resource. In this example, the name is HELLORIBBON_RIBBON. That is, the name is whatever is specified
in the /name switch, uppercased, with "_RIBBON" appended.

We should also tell Visual Studio what files uicc creates by setting the Outputs field to "$(InputName).bml;$(InputName)ids.h;$(InputName).rc".

Next, we add the resources from ribbon.rc to our app's resources. In the Resource View tab, right-click
HelloRibbon.rc and select Resource Includes. In the Compile-time directives edit box, add:

#include"ribbon.rc"

Now when the app is compiled, the app's resources will include any resources that were listed in ribbon.rc.
uicc also verifies that the XML contains no errors, and doesn't break any of the Ribbon's layout rules (for example,
having the same command appear more than once in a group). If uicc finds any errors, it will fail to compile the
XML, and the project will not build.

Loading the Ribbon

The last step is to initialize the Ribbon using the compiled version of the XML. We do this by adding a call
to IUIFramework::LoadUI() in CMainFrame::OnCreate():

With these changes, all of the required elements are in place, and uicc won't issue any more warnings.

Communicating with the Ribbon

We've already seen the IUIFramework interface, which our app uses to set up and tear down the Ribbon
framework. There is another interface that our app uses to communicate directly with the Ribbon: IUIRibbon.
The Ribbon passes this interface to our app via IUIApplication::OnViewChanged(), so we'll start by
filling in that method.

First, add a member to CMainFrame that will hold the IUIRibbon interface:

// In MainFrm.h:
CComQIPtr<IUIRibbon> m_pRibbon;

CMainFrame::OnViewChanged() is called when the Ribbon is created, destroyed, or resized. (Technically,
it deals with application views, not the Ribbon specifically, but the Ribbon is the only view that has been
defined so far.) The parameters to OnViewChanged are:

uViewID: The view ID, currently always 0.

nType: The view type, currently always UI_VIEWTYPE_RIBBON.

pView: An IUnknown interface provided by the view.

nVerb: The action that the view is performing: UI_VIEWVERB_CREATE, UI_VIEWVERB_DESTROY,
or UI_VIEWVERB_SIZE.

nReason: Not currently used.

When nVerb is UI_VIEWVERB_CREATE, the Ribbon is being created and we can query it
for an IUIRibbon interface. When nVerb is UI_VIEWVERB_DESTROY, the Ribbon
is going away, so we release the IUIRibbon interface:

A more interesting case is UI_VIEWVERB_SIZE. This tells us that the Ribbon is changing size, being
hidden, or being shown. Since that affects the layout of the main frame, we get the Ribbon's new height in pixels
and lay out the frame window:

CFrameWindowImpl::UpdateLayout() positions the various kinds of bars that WTL supports -- rebars,
toolbars, and status bars -- and then positions the view window to take up the remaining space. Since WTL doesn't
know about the Ribbon, we need to override UpdateLayout() and use the Ribbon's height as part of the
calculations. Our override is pretty similar to CFrameWindowImpl::UpdateLayout(), but it determines
how many pixels to reserve at the top of the client area by looking at m_cyRibbon:

After adding this UpdateLayout() override, you can try minimizing the Ribbon and the view window
will resize accordingly:

If you make the window small enough, the Ribbon will hide itself entirely. Our UpdateLayout() handles
that case as well.

Handling Notifications from Commands

IUICommandHandler

The next interface we'll use is IUICommandHandler. The app implements this interface, and the Ribbon
calls its methods to read properties for each command and notify the app that it should execute a command.

When the Ribbon parses the compiled XML, it asks the app for a COM interface on each command. The app must return
an IUICommandHandler interface for a command to be functional. This interface can be implemented by
any COM object, but for our sample app, we'll add the interface directly to CMainFrame:

Creating and destroying IUICommandHandlers

The Ribbon will call IUIApplication::OnCreateUICommand() once per command to get an IUICommandHandler
interface, and IUIApplication::OnDestroyUICommand() once when it no longer needs the interface. Since
CMainFrame implements IUICommandHandler for every command, CMainFrame::OnCreateUICommand()
is simple:

Inserting C command identifiers into the Ribbon XML

Notice that OnCreateUICommand() and OnDestroyUICommand() have command ID parameters.
By default, uicc generates IDs automatically. If you look at the ribbonids.h file, you'll see lines like
the following:

#define cmdClickMe 7

where uicc has used the Name attribute of a <Command> tag to create a C identifier.
Let's see how to control these identifiers and make them follow the C convention of being all uppercase.

Going back to the <Command> tag for the Click Me button:

<CommandName="cmdClickMe"LabelTitle="Click me"/>

we can add a Symbol attribute that sets the identifier's name, and an Id attribute
that sets its value. For example:

(I've used RIDC as a prefix by adding R (ribbon) in front of the conventional prefix
IDC.) With this change, ribbonids.h will now have:

#define RIDC_CLICK_ME 42

Name can be any legal C identifier, and Id can be an integer between 2 and 59999 inclusive.
The Id value can be written as decimal or hexadecimal.

Executing a command

When the user clicks a button, the Ribbon calls the associated IUICommandHandler::Execute() method.
The parameters to Execute() are:

uCmdID: The command ID.

nVerb: A constant that indicates what kind of action the user is taking. In the sample app, the
verb is always UI_EXECUTIONVERB_EXECUTE.

pKey, pCurrVal: For some commands, the Ribbon passes a property and its new value
in these parameters.

pCmdProperties: A IUISimplePropertySet collection containing additional properties
about the command. The sample app does not use this parameter.

Depending on the type of command, the Ribbon may pass Execute() some information about the state
of the command. For example, when the user clicks a toggle button, the Ribbon passes the new state of the button
(toggled off or on) in the pCurrVal parameter. We'll see an example later that uses this info. A simple
push button has no extra info, so we just look at the command ID to know which command is being executed:

Notice that the case statement uses the RIDC_CLICK_ME identifier that we set in the
<Command> tag.

Using Toggle Buttons

Another type of control you can put in the Ribbon is a toggle button. These buttons function like check
boxes, in that each click toggles the state between on (pressed) and off (not pressed).

Adding a ToggleButton control

We'll use a toggle button to show and hide the status bar, similar to the View|Status Bar command that's
created by the WTL AppWizard. We'll need two new commands, one for a new group, and one for the button:

Writing IUICommandHandler::Execute for a ToggleButton

The implementation of IUICommandHandler::Execute() is passed a key/value pair in the form of a
PROPERTYKEY and a PROPVARIANT. When Execute() is called because the user
clicked a toggle button, the key is UI_PKEY_BooleanValue, and the value is a boolean that indicates
the new state of the button: true means the button is now toggled on, and false means it's toggled off.

The header file UIRibbonPropertyHelpers.h contains some helper functions that make it easier to get and
set values in PROPVARIANTs. Since the value sent for a toggle button is a boolean, we can use the
UIPropertyToBoolean() function to read the value from the PROPVARIANT:

Once you add this code to CMainFrame::Execute(), you can click the toggle button and the status
bar will be shown or hidden with every click.

Setting command properties

Since a toggle button is toggled off by default, the initial state of our button isn't what we want; the status
bar starts out visible, so the button should start in the toggled-on state. However, there is no element in the
XML file for setting the button's initial state. Instead, the Ribbon queries for that property right after the
IUICommandHandler for that button is created.

When the Ribbon needs to query a property of a command, it calls that command's IUICommandHandler::UpdateProperty()
method, which can return the property's new value in a PROPVARIANT. Here's how we set the initial
state of the toggle button:

This is essentially doing the opposite of the code we just saw in Execute(). It uses another helper
function in UIRibbonPropertyHelpers.h, UIInitPropertyFromBoolean(), to store a boolean value
in a PROPVARIANT. All of the UIInitPropertyFromXxx() helpers take the PROPERTYKEY
and the new value so they can check that the value is compatible with the property's data type. If you pass an
incompatible data type, the compiler will issue an error.

If you set a breakpoint at the beginning of CMainFrame::UpdateProperty(), you'll see that it gets
called a lot. There are many optional properties in the Ribbon XML that we haven't set. The Ribbon calls UpdateProperty()
to query for all of those properties, and falls back to reasonable defaults if the function returns E_NOTIMPL.
That is why we have to check the key parameter so we know when the Ribbon is querying for the button's
toggle state, and not some other property whose default value is sufficient.

Additional Properties of Commands

Adding tooltips and keytips

The Ribbon has built-in support for keyboard navigation. If you press the Alt key, you'll see tooltips
that tell you how to navigate through the Ribbon's elements:

These navigation tooltips are called keytips, and can be customized with the Keytip attribute
of the <Command> tag. For example, to change the Main tab's navigation key to "M",
make this change to the tab's <Command> tag:

<CommandName="tabMain"Symbol="RIDT_MAIN"LabelTitle="Main"Keytip="M"/>

This string, along with other string attributes, all show up as resources in the ribbon.rc file that
uicc creates. That way, the strings can be localized. The string resource IDs begin at 60001, but the IDs can be
customized just like the command IDs. To customize a string attribute, you create a sub-tag called <Command.Keytip>
to hold the keytip properties. Within that tag, create a <String> tag that contains the C identifier
and resource ID:

Each command can also have a tooltip that's shown when the mouse hovers over the button. The tooltip can have
a title, which is shown in bold, and a description. These strings are set through the TooltipTitle
and TooltipDescription attributes of a <Command> tag. Here's how to add a tooltip
to the toggle button:

As with the Keytip, you can change the IDs of the tooltip strings by using a <String>
tag. Here's what the customized tooltip looks like:

Assigning images to buttons

Our buttons look pretty boring without any graphics, so let's see how to add some. The Ribbon supports only
two graphics formats: 32bpp BMP files for normal images, and 4bpp BMP files for high-contrast images. uicc will
issue an error if you use any other type of graphic. (I must apologize up-front for my lame-looking graphics. I
am galactically incapable of drawing anything good myself, so I've borrowed graphics from the sample Ribbon apps
in the Windows SDK.)

Each command can have four sets of images: large, small, large high-contrast, and small high-contrast. The Ribbon
chooses whether to use large or small images based on where the command appears. The two buttons we've added so
far are large buttons, so they will use large images. If you add those commands to the QAT, those buttons will
use small images. The two sets of high-contrast images are used when the system is using a high-contrast visual
theme; the choice about which image size to use remains the same.

The images are set via properties of the <Command> tag. Here is the XML that sets the large
and small images to use for the Show status bar button:

The Source attributes are file paths relative to where the XML file is, so in this case the files
are in a res subdirectory. uicc will include these images in the ribbon.rc file and generate
IDs for them. As with strings, you can customize the resource ID and the C identifier for an image by adding attributes
to the <Image> tag:

Within each of the four sets of images, there can be up to four <Image> tags for use at various
DPI settings. In this example program, we have just one image for the default DPI of 96. This is fine, because
the Ribbon will scale the images as necessary if the system is using a higher DPI setting.

Here's how the Ribbon looks with images on the two buttons:

Setting up the Application Menu

The Applications menu is the Ribbon element that's analogous to the File menu in apps with a regular
menu. The Applications menu is accessed through the dropdown button to the left of the Main tab. Its contents
are listed in a <Ribbon.ApplicationMenu> tag that is a child of the <Ribbon>
tag.

The Applications menu contains two sub-elements, a most-recently-used file list and a menu of commands. The
MRU list is set with a <ApplicationMenu.RecentItems> child tag, and the menu's contents are
controlled by one or more <MenuGroup> child tags.

Here's the XML that shows the contents of the Applications menu in our sample app:

The MRU list is just an empty placeholder, to show what it looks like.

The menu contains two commands in one group. You can create separators in the menu by closing one <MenuGroup>
tag and starting another.

The mnemonic for a command that appears in the menu is set by putting an ampersand in the menu item text, as
with traditional menus. The ampersand must be escaped in XML and written as "&amp;". If the command
is used elsewhere in the Ribbon, the ampersand is ignored and the Keytip attribute is used instead.

Saving Ribbon Settings

The last thing we'll add to the sample app is the ability to save Ribbon settings when the app closes. If you
change the contents of the QAT or minimize the Ribbon, those changes are lost when you close the app. To fix that,
we'll use two IUIRibbon methods for loading and saving settings. First, add a string member to CMainFrame
that holds the data file path:

// In MainFrm.h:
CString m_sSettingsFilePath;

Since this path won't change while the app is running, we can initialize it in the CMainFrame constructor:

LoadRibbonSettings() calls IUIRibbon::LoadSettingsFromStream() to load the settings.
Since that method takes an IStream interface on the data, we call SHCreateStreamOnFileEx()
to get an IStream interface that can be used to read the file.

If the file does not exist or can't be opened, we don't call LoadSettingsFromStream(), and the
Ribbon will start out in the default state.

SaveRibbonSettings() is similar. We get an IStream interface that can be used to write
to the file and reset the file size to zero so that any existing contents are erased. Then we call IUIRibbon::SaveSettingsToStream()
to save the settings to the file.

Now, when you close the app, any changes you make to the Ribbon size and QAT will be preserved the next time
you run the app.

Conclusion

In this article, we've seen the basic steps necessary to include the Ribbon in an application. Next time, we'll
get an in-depth look at how commands are organized in groups, and how to customize a group's layout.

Share

About the Author

Michael lives in sunny Mountain View, California. He started programming with an Apple //e in 4th grade, graduated from UCLA with a math degree in 1994, and immediately landed a job as a QA engineer at Symantec, working on the Norton AntiVirus team. He pretty much taught himself Windows and MFC programming, and in 1999 he designed and coded a new interface for Norton AntiVirus 2000.
Mike has been a a developer at Napster and at his own lil' startup, Zabersoft, a development company he co-founded with offices in Los Angeles and Odense, Denmark. Mike is now a senior engineer at VMware.

He also enjoys his hobbies of playing pinball, bike riding, photography, and Domion on Friday nights (current favorite combo: Village + double Pirate Ship). He would get his own snooker table too if they weren't so darn big! He is also sad that he's forgotten the languages he's studied: French, Mandarin Chinese, and Japanese.

You can do those things, but you can't insert or remove controls without destroying one ribbon and creating another. You can show and hide some parts (like groups or tabs) using application modes. You can enable or disable a button with IUIFramework::SetUICommandProperty, passing UI_PKEY_Enabled as the property.

So how much did you pay for your coffee today? I think you should ask for your money back.

Oh take me out to the climber's crag, take me to the sun. Buy me some white gold and cams for my rack; I don't care if I ever get back. Rope, rope up with a partner. Let them lead the climb. They can way-lay the high belay and you can just take your time. Oh take me out to the climber's crag, take me into the sun. A rope on back, a climbers rack, good friends and strangers come on!

Most of my clients are mostly neutral when it comes to Windows UI elements. Until, of course, it comes to ribbons. I am quite surprised by how many people really hate it. I was just wondering what your experience has been?

I enjoy the ribbons but it took me a while to realize that ribbons are not re-arranged menu commands. As soon as I got over the "What menu is this supposed to be and where is the $@$ at?". I have since started to enjoy them. I like that I can collapse them when I do not need them. I like that there are choices that are distinctly unique to Ribbons that menus just cannot communicate given their limited canvas.

I think ribbons are cool but I think it would be nifty if you could have a ribbon/menu selector. If you want the ribbon keep it in the ribbon position if you want menus slide it over to menus.