Archive for June, 2009

Windows 7 Ribbon – Part 1 – How to Integrate a Simple Ribbon to your MFC Application?

The Office 2007 changed the the conventional menu to a new vibrant, beautiful, and useful(??) ribbons. After that many third party libraries (both commercial and non commercial) vendors provided components to integrate ribbons to our application. Finally Microsoft heed the MFC guys crying a loud to get support on ribbons. Microsoft included Ribbons and other office style controls with MFC Feature Pack for Visual Studio 2008.

The following figure depicts the anatomy of a typical Ribbon.

image

In the new version of Windows, Windows 7 , it supports ribbons natively and Microsoft allows us to create it using Ribbon Frame Work.  Few Accessories application like MS Paint, Wordpad etc. got UI lift with Windows Ribbons.

Developer can create ribbon using Ribbon Markup Language (similar to XML format). For the Windows Ribbon framework (Ribbon) to consume the Ribbon markup file, the markup file must be compiled into a binary format resource file. A dedicated Ribbon markup compiler, the UI Command Compiler (UICC), is included with the Microsoft Windows Software Development Kit (SDK) (7.0 or later) for this purpose. In addition to compiling the binary version of the Ribbon markup, the UICC generates an ID definition header file that exposes all markup elements to the Ribbon host application and a resource file that is used to link the binary markup to the host application at build time.

The workflow for the Ribbon is as follows

Ribbon-Flow

OK let’s create a simple ribbon step by step. You should have Windows 7 SDK installed and Visual Studio 2005 or above is required to compile this application. I’m taking a MFC Application do this instead of a Win32 application. I’m just creating a new MFC Dialog Based Application.

We can categorize the ribbon creation in to two categories.

  • XML Markup, used to define the Ribbon structure and organization of controls
  • C++ COM interfaces, used to initialize and handle events

Step 1: Create the XML file with your ribbon. Add this XML for the solution. The following XML is a simple ribbon contains the application a Tab,Group and a button inside it.

1

<application xmlns="http://schemas.microsoft.com/windows/2009/Ribbon">
  <application.Commands>
    <!--Commands for the whole ribbon-->
    <!--Tab name-->
    <command Name="TabHome" Symbol="cmdTabHome" Id="30000" LabelTitle="Home"/>
    <!--Group under tab-->
    <command Name="GroupMain" Symbol="cmdGroupMain" Id="30001" LabelTitle="Main"/>
    <!--button name and properties-->
    <command Name="MyButton" Symbol="cmdMyButton" Id="30002" LabelTitle="My Button">
      <command.TooltipTitle>My Button</command.TooltipTitle>
      <command.TooltipDescription>My Button</command.TooltipDescription>
      <command.SmallImages>
        <!--specify the bitmap. Only .bmp format is supported-->
        <image Source="res/New.bmp"/>
      </command.SmallImages>
    </command>

  </application.Commands>
  <application.Views>
    <ribbon>
      <!--organize the view-->
      <ribbon.Tabs>
        <tab CommandName="TabHome">
          <group CommandName="GroupMain">
            <button CommandName="MyButton" />
          </group>
        </tab>
      </ribbon.Tabs>
    </ribbon>
  </application.Views>
</application>

Step 2: Specify the custom build option for the XML file. The XML file has to be compiled with UICC.exe application. If Visual Studio can’t find the binary, locate it from your Microsoft SDK directory in program files and specify the path in the PATH variable. In the custom build rule, add following string as command line

uicc.exe MenuRibbon.xml MenuRibbon.bml /res:MenuRibbon.rc /header:MenuRibbonRes.h

Under the outputs specify the following string.

MenuRibbon.bml;MenuRibbon.rc;MenuRibbonRes.h
7

Step 3 – Add Support for ATL

Active template library (ATL) support is required to implement this functionality. In the project properties, specify ATL support as follows

6

Step 4 – Implement the IUIApplication interface for your application

It’s necessary to implement the IUIApplication interface for our application to support ribbons. I’ve wrapped inside a class for convenient use. Currently it’s not necessary to provide any implementation for derived interfaces.

#include "stdafx.h"
#include <atlbase.h>
#include <atlcom.h>
#include <initguid.h>
#include <uiribbon.h>

class CRibbonImplementer:
	public CComObjectRootEx<ccomMultiThreadModel>,
	public IUIApplication
{
public:
BEGIN_COM_MAP(CRibbonImplementer)
COM_INTERFACE_ENTRY(IUIApplication)
END_COM_MAP()

	// unimplemented methods
	STDMETHOD(OnViewChanged)(UINT32 nViewID, __in UI_VIEWTYPE typeID, __in IUnknown* pView, UI_VIEWVERB verb, INT32 uReasonCode)
	{
		return E_NOTIMPL;
	}
	STDMETHOD(OnCreateUICommand)(UINT32 nCmdID, __in UI_COMMANDTYPE typeID, __deref_out IUICommandHandler** ppCommandHandler)      {          return E_NOTIMPL;      }      STDMETHOD(OnDestroyUICommand)(UINT32 commandId, __in UI_COMMANDTYPE typeID, __in_opt IUICommandHandler* pCommandHandler)
	{
		return E_NOTIMPL;
	}
};

class CRibbonHandler
{
private:
	IUIFramework* m_pFramework;

public:

	CRibbonHandler() : m_pFramework( 0 )
	{
	}
	~CRibbonHandler()
	{
		Destroy();
	}

	HRESULT Init( HWND hWnd)
	{
		HRESULT hr = ::CoCreateInstance(CLSID_UIRibbonFramework, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&m_pFramework));
		if(FAILED(hr))
			return hr;
		CComObject<cribbonImplementer> *pApplication = NULL;
		hr = CComObject<cribbonImplementer>::CreateInstance(&pApplication);
		if(FAILED(hr))
			return hr;

		hr = m_pFramework->Initialize(hWnd, pApplication);
		if(FAILED(hr))
			return hr;

		hr = m_pFramework->LoadUI(GetModuleHandle(NULL), _T( "APPLICATION_RIBBON"));

		return hr;
	}

	void Destroy()
	{
		if( m_pFramework )
		{
			m_pFramework->Release();
			m_pFramework = 0;
		}
	}
};

 

Step 5 – Integrate the output ribbon rc file and header with application resource.

Open the resource file (RiboonMFC.rc) file in source code mode. (right click on rc file and opt for “View Code”).

specify

#include “MenuRibbonRes.h”
#include “MenuRibbon.rc”

in application’s rc file

Step 6: Initialize COM and load the ribbon to the dialog

This operation can be done inside the app class of the application. Inside the InitInstance function, specify the following code. Note that we’re not calling DoModal inside the InitInstance but instead, we’re calling Create function of the dialog class and call RunModalLoop till user closes the dialog.

BOOL CRibbonMFCApp::InitInstance()
{
	CoInitialize( 0 );
// other initialization code can be put here like InitCommonControlEx etc.
	CRibbonMFCDlg dlg;
	m_pMainWnd = &dlg;

	CRibbonHandler ribbon;
	dlg.Create(dlg.IDD );

	HRESULT hr = ribbon.Init( dlg.GetSafeHwnd());
	if (FAILED(hr))
		return FALSE;

	dlg.RunModalLoop();

	return FALSE;
}

Now you’re done

Before compiling ensure that the bitmap specified for the ribbon button is existing in the solution file. Otherwise import it to the solution file.

You can see the application as follows if you successfully compiled your project We’ve not handled any events for the controls that we’ll learn in the next instalment.

8


Thought for the Day: Set Yourself Free!

Set yourself free from anything that might hinder you in becoming the person you want to be. Free yourself from the uncertainties about your abilities or the worth of your dreams, from the fears that you may not be able to achieve them or that they won’t be what you wanted.

Set yourself free from the past. The good things from yesterday are still yours in memory; the things you want to forget you will, for tomorrow is only a sunrise away. Free yourself from regret or guilt, and promise to live this day as fully as you can.

Set yourself free from the expectations of others, and never feel guilty or embarrassed if you do not live up to their standards. You are most important to yourself; live by what you feel is best and right for you. Others will come to respect your integrity and honesty.

Set yourself free to simply be yourself, and you will soar higher than you’ve ever dreamed.

- Edmund O’Neill


  • Translate to yours!

  • Keep this running!

  • The People!

  • If I’ve proven, be connected

  • Recent Posts

  • Pages

  • Copyright © 1996-2010 Reflections of my thoughts..... All rights reserved.