These are the steps required to do get your application ribbon enabled.

  • Create a 'myapp.ribbon.xml' which has the layout definition of the Ribbon.

    A sample ribbon markup looks like this.

<?xml version='1.0' encoding='UTF-8'?>

<Application xmlns="http://schemas.microsoft.com/windows/2009/Ribbon>">

<Application.Commands>

</Application.Commands>

<Application.Views>

<Ribbon Name="MyApp">

<Ribbon.ApplicationMenu>

<ApplicationMenu CommandName="cmdAppMenu">

. . .

</ApplicationMenu>

</Ribbon.ApplicationMenu>

<Ribbon.Tabs>

<Tab CommandName="cmdTabHome">

<Tab.ScalingPolicy>

. . .

</Tab.ScalingPolicy>

<Group CommandName="cmdChunkClipboard" SizeDefinition="BigButtonsAndSmallButtonsOrInputs">

. . .

</Group>

</Tab>

. . .

</Ribbon.Tabs>

. . .

</Ribbon>

</Application.Views>

</Application>

    

  • Setup Visual file and intencl.exe

    We should create a custom build step for the markup file

uicc.exe /b myapp.ribbon.xml myapp.ribbonb /header:ids.h /res:myapp_ribbon.rc /name:myapp

  • Add the following files as common includes

#include <UIRibbon.h>

#include <UIRibbonPropertyHelpers.h>

    

  • Resource inclusion

    The generated resource file 'myapp_ribbon.rc' should be included in the application resource file( say myapp.rc)

#include "ids.h"

#include "myapp_ribbon.rc"

      

  • Initialization and un-initialization of the Ribbon framework in the App constructor and destructor respectively?

          

::CoCreateInstance(CLSID_UIRibbonFramework, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&m_spIUIFramework));

and

m_spIUIFramework->Destroy();

      

  • Implement IUIApplication, which receives the application level notification from ribbon

class CApplication

: public CComObjectRootEx<CComMultiThreadModel>

, public IUIApplication

{

public:

BEGIN_COM_MAP(CApplication)

COM_INTERFACE_ENTRY(IUIApplication)

END_COM_MAP()

      

STDMETHOD(OnViewChanged)(UINT viewId, __in UI_VIEWTYPE typeID, __in IUnknown* pView, UI_VIEWVERB verb, INT uReasonCode);

    

STDMETHOD(OnCreateUICommand)(UINT32 nCmdID,

__in UI_COMMANDTYPE typeID,

__deref_out IUICommandHandler** ppCommandHandler);

STDMETHOD(Activate)(BOOL fInputActive);

    

STDMETHOD(OnDestroyUICommand)(UINT32 commandId, __in UI_COMMANDTYPE typeID, __in_opt IUICommandHandler* commandHandler);

};

      

  • Initialize the Ribbon

    Call the following initialization code by passing HWND of the parent frame and pointer to IUIFramework which will get the initial call backs from the ribbon

CComObject<CApplication> *pApplication;

hr = CComObject<CApplication>::CreateInstance(&pApplication);

if (SUCCEEDED(hr))

{

CComPtr<IUIFramework> m_spIUIFramework;

HRESULT hr = spIUIFramework->Initialize(*pFrame, pApplication); //Here *pFrame - HWND of framewnd

if (SUCCEEDED(hr))

{

//Load the ribbon

hr = spIUIFramework->LoadUI(GetModuleHandle(NULL) , "myapp_ribbon");

}

}

      

  • Implement handler class (here I am creating a generic handler class) which implements IUICommandHandler

    This class receives execute command when we press a ribbon concept. In addition this class is responsible for providing the ribbon with dynamic information of the concepts like enabled, checked etc.

    Here for simplicity I am reusing CApplication class for this purpose.     

class CApplication

: public CComObjectRootEx<CComMultiThreadModel>

, public IUIApplication

, public IUICommandHandler

{

public:

BEGIN_COM_MAP(CApplication)

COM_INTERFACE_ENTRY(IUIApplication)

COM_INTERFACE_ENTRY(IUICommandHandler)

END_COM_MAP()

      

STDMETHOD(OnViewChanged)(UINT viewId, __in UI_VIEWTYPE typeID, __in IUnknown* pView, UI_VIEWVERB verb, INT uReasonCode);

    

STDMETHOD(OnCreateUICommand)(UINT32 nCmdID,

__in UI_COMMANDTYPE typeID,

__deref_out IUICommandHandler** ppCommandHandler);

{

*ppCommandHandler = this; // Register the command handler class as the same class

AddRef();

return S_OK;

}

      

STDMETHOD(Activate)(BOOL fInputActive);

    

STDMETHOD(OnDestroyUICommand)(UINT32 commandId, __in UI_COMMANDTYPE typeID, __in_opt IUICommandHandler* commandHandler);

      

// User action callback, with transient execution parameters

STDMETHOD(Execute)(UINT nCmdID,

UI_EXECUTIONVERB verb,

__in_opt const PROPERTYKEY* key,

__in_opt const PROPVARIANT* ppropvarValue,

__in_opt IUISimplePropertySet* pCommandExecutionProperties)

{

MessageBox(NULL, L"Got the event", L"Action message", MB_OK); //Recieves messages for any action on ribbon buttons

}

      

// Asks the application for a specific property value

STDMETHOD(UpdateProperty)(UINT nCmdID,

__in REFPROPERTYKEY key,

__in_opt const PROPVARIANT* ppropvarCurrentValue,

__out PROPVARIANT* ppropvarNewValue);

};

 

 

The following image represents how the messages are passed between Ribbon Framework and the application.

 

More information on Ribbon Markup, Windows Ribbon Framework Developer Guides