The Transformed XML Explorer in MFC

A visual upgrade is often welcome. Aside from the aesthetics, it also helps to introduce new features and new ways to complete tasks. Microsoft made such a move with the launch of its Office Suite 12. In this, they launched the ribbon. If you're interested in making your application compatible with the ribbon, keep reading.

Contributed by
Rating: 5 stars5 stars5 stars5 stars5 stars / 2
October 27, 2009
Rate this Article:
MEH MEH++


SEARCH ASP FREE
TOOLS YOU CAN USE

advertisement

The ribbon is the result of a massive amount of customer research that Microsoft conducted. Over the past few years, the ribbon has managed to redefine how we interpret Office applications -- and to be honest, most of us have become addicted to its context-sensitive toolbar system.

This article is the second part of a two-part series in which I am looking into how to upgrade/extend your old-school application. The title of the first part is New Features for the Statusbar in MFC and you can find it here on the ASP Free section of the Developer Shed network. In the first part, I showed how to apply the Office style to your application. In this second part, I will show how to add the new tab-based multi-window system and how to add a ribbon to your application.

I will stick with the XML Explorer source code and continue its improvement and extension. Adding the tab support is one of the simplest tasks. First, you need to make sure that in the Application class on the initialization of the instance, the InitContextMenuManager () method is called. This will create the object that will handle future tasks; I have already done this in the first task.

Now we just need to tell the application to use the style. The CMDTabInfo is a class through which you can customize how to perform these tasks. Pass it after you build it as an argument as shown below:

CMDITabInfo tabInfo; // Declare the object

 

//customize it

tabInfo.m_bAutoColor = true;

tabInfo.m_bDocumentMenu = true;

 

//pass it for the Manager

EnableMDITabbedGroups (true, tabInfo);

Now, once you run the application, you can observe it in action:

 

The table below will explain the other configuration options of the tab system:

CMDITabInfo Member

Value options and effects

m_style

STYLE_3D -3D style.

STYLE_3D_ONENOTE - Microsoft OneNote style.

STYLE_3D_VS2005 - Microsoft Visual Studio 2005 style.

STYLE_3D_SCROLLED - 3D style with rectangle tab labels.

STYLE_FLAT_SHARED_HORZ_SCROLL - Flat style with shared horizontal scroll bar.

STYLE_3D_ROUNDED_SCROLL - 3D style with round tab labels.

m_bActiveTabCloseButton

FALSE => Place close button at right of the tab area.

m_bTabIcons

TRUE => enable document icons on MDI tabs.

m_bAutoColor

Enable or disable the auto color.

m_bDocumentMenu

TRUE => Enable document menu at the right edge of the tab area.

m_bEnableTabSwap

User can change (or not change) the positions of the tabs by dragging them.

m_bFlatFrame

TRUE => give each tab window a flat frame.

m_bTabCloseButton

TRUE => each tab displays a close button on the right edge of the tab.

m_bTabCustomTooltips

TRUE => tabs display tooltips.

m_tabLocation

LOCATION_BOTTOM: the tabs; labels are located at the bottom of the page.

LOCATION_TOP: the tabs' labels are located at the top of the page.

m_nTabBorderSize

Specifies the border size, in pixels, of each tab window.

The Ribbon

Making applications using the new Ribbon system is certainly not an easy task. I'm not saying that it is very complicated and that it requires heavy documentation. The problem is that Microsoft obligates (or at least it did at the beginning) any company using the product of their research (for commercial purpose at least) to sign the Ribbon Fluent Guidelines.

Microsoft also filled a patent application form for it. No patent has been issued so far. It is debatable that the Ribbon has its origins in the tabbed toolbars of  applications such as Macromedia HomeSite, Dreamweaver and Borland Delphi. Possibly because of this, the Office Fluent Guidelines (which try to create a consistent user experience with the ribbon) have recently been published on the MSDN here.

Meanwhile, the software giant from Redmond has also developed a framework for the Ribbon. I will talk about this in future articles. This tries to make using the ribbon in applications easier and accessible to more people. Support for both C++ and C# is present. However, for now I am going to stick with what the feature pack has to deliver.

Before we add any code to our application, we need to add the resources that will contain the images to show. The images you use should be BMP with 32-bit depth. The ones below satisfy these criteria. Use the resource view to add the files, and after the properties tab, change their name as follows:

IDB_FILE_LARGE:

IDB_FILE_SMALL

IDB_MAIN_ICON_RIBBON:

 

Add the members to the Mainframe class:

CMFCRibbonApplicationButton m_MainButton;

CMFCRibbonBar m_wndRibbonBar; 

Creation and Menu

 

Now it remains to create the ribbon. Add a function in which we are going to handle the tasks considering the ribbon. I have chosen the name of InitRibbon ():

 

protected:

bool InitRibbon ();

 

Now create the ribbon in the OnCreate method of the mainframe and call the initialization process:

 

if (! m_wndRibbonBar.Create (this))

{

return -1; //Error in the creation of the ribbon

}

 

 

InitRibbon ();

I docked the toolbar manually to the down side of the application, so we can better see what we are doing. Now we set the image for the main ribbon button and add a tooltip text for it:

bool CMainFrame::InitRibbon ()

{

 

// Load the images and set the text for the main button

m_MainButton.SetImage (IDB_MAIN_BUTTON_RIBBON);

m_MainButton.SetToolTipText (_T ("File menu"));

m_MainButton.SetText (_T ("nf"));

 

m_wndRibbonBar.SetApplicationButton (&m_MainButton,

CSize (60, 60));

return true;

}

We can add menu points by first adding a main category. The main category will have a name and two image lists. The first contains the small icons (the ones you can see, for instance, in the quick access toolbar) and the second the images for the large icons (in the menu itself).

Adding menu points resembles adding buttons to the main panel. First specify the ID of the menu item, and then the text to show near it; finally, specify the index of the small and large icon inside the image list you specified. The examples underneath will make this clear:

CMFCRibbonMainPanel* pMainPanel =

m_wndRibbonBar.AddMainCategory(

_T("Main"), IDB_FILE_SMALL, IDB_FILE_LARGE);

 

pMainPanel->Add(new

CMFCRibbonButton(ID_FILE_NEW, _T("New"), 0, 0));

pMainPanel->Add(new

CMFCRibbonButton(ID_FILE_OPEN, _T("Open"), 1, 1));

pMainPanel->Add(new

CMFCRibbonButton(ID_FILE_SAVE, _T("Save"), 2, 2));

pMainPanel->Add(new

CMFCRibbonButton (ID_FILE_SAVE_AS, _T ("Save As"), 3, 3));

 

The Quick access toolbar functionality is a built-in item for the ribbon. As soon as there are some menu points, you can customize them to add it there. You only need to specify the commands for the items to make this option possible.

// Add quick access toolbar commands:

CList<UINT, UINT> lstQATCmds;

 

lstQATCmds.AddTail(ID_FILE_NEW);

lstQATCmds.AddTail(ID_FILE_OPEN);

lstQATCmds.AddTail(ID_FILE_SAVE);

lstQATCmds.AddTail(ID_FILE_PRINT_DIRECT);

 

m_wndRibbonBar.SetQuickAccessCommands (lstQATCmds);

As you can observe, these commands took over the behavior of the ones on the command bar. Therefore, they are grayed out when the option makes no sense and are activated once it is possible. Using the same system, we can easily add an exit menu item to the bottom with the following line:

pMainPanel->AddToBottom (

new CMFCRibbonMainPanelButton (ID_APP_EXIT,

"Out of here", 15));

 

Now all we need to add to make it look close to the Office style is the recent file list. For this, we need to perform some tasks beforehand. The first one is a lapse of the initial developer of the program. It failed to create the serialization system and instead came up with a custom function that handles all this. We need to call this from the serialization section. Open the xmltreeDoc.h and find the Serialize function. Extend it as follows:

if (ar.IsStoring())

{

 

}

else

{

CString temp;

LoadXML (ar.GetFile () ->GetFilePath (), temp);

}

Second, we need to add a file to the recent list whenever we open a new file. Open the xmltree.cpp file and find the OnFileOpen function at the end. As soon as the code snippet asks for the file, add this to the list with the function beneath:

//the call for the Path name

CString m_File1 = dlg.GetPathName ();

 

//Add these lines of code:

static_cast<CXmltreeApp*> (

AfxGetApp ())->AddToRecentFileList(m_File1);

Third, add to the beginning of the LoadXML (inside xmltreeDoc.cpp) method the following C++ code:

CString name;

 

name.SetString (filename.GetBuffer () + filename.ReverseFind (_T ('')) +1);

this->SetTitle (name);

This will set the name of the documents according to the input. Now all we need to do is ask for the ribbon to display the recent file list:

pMainPanel->AddRecentFilesList (_T ("Our Recent documents"));

We could also add a separator, for instance after adding the open menu item:

pMainPanel->Add (new CMFCRibbonSeparator (TRUE));

The Ribbon Itself

Although all this contributes to the effect created by using a ribbon, the central start remains the ribbon bar. In order to create one, first you need to understand its construction. The image below attempts to explain this:

The most important is the contextual tab with its sub-groups. We will try to transform the functions from the toolbar to this. First, we need to add a new tab to the ribbon:

CMFCRibbonCategory* pCategoryGeneral = m_wndRibbonBar.AddCategory (_T ("General"),

IDR_MAINFRAME, IDB_FILE_LARGE);

We add a new category for which we specify its name and an image list for the small icons (I am going to use IDR_MAINFRAME) and the large icons (IDB_FILE_LARGE). These lists must contain the images for all the controls you intend to include in this tab. For example, the Home tab above should contain all the images for the paste, copy, left, right and so forth.

The groups you can find inside a category (tab) can be shown on the Quick Access Toolbar. For this reason, we need to assign to each of these a small icon. The easiest way to do this is to load inside a CMFCToolBarImages object an image from the resource. Afterward, you can extract the icons from this by specifying the index of the one desired. Add one of these variables to the Mainframe class. Then extend the initialization of the ribbon:

m_PanelImages.SetImageSize (CSize (15, 15));

m_PanelImages.Load (IDR_MAINFRAME);

 

CMFCRibbonPanel* View_As =

pCategoryGeneral->AddPanel (_T ("View As"), m_PanelImages.ExtractIcon (0));

I already added the first group. Now we can populate with various pre-defined items with the usage of a single function: the Add:

View_As->Add (new CMFCRibbonButton (ID_VIEW_SMALLICON,

_T ("Small Icon"), 7));

View_As->Add (new CMFCRibbonButton (ID_VIEW_LARGEICON,

_T ("Large Icon"), 8));

View_As->Add (new CMFCRibbonButton (ID_VIEW_LIST,

_T ("View List"), 9));

View_As->Add (new CMFCRibbonButton (ID_VIEW_DETAILS,

_T ("Details"), 0, 10));

 

In the case of buttons, just specify the control ID of the button (taken from the toolbar or menu item), and specify the name you want to appear near it. Finally, you can choose a small icon from the small image list with a single integer number as a parameter, or add a large image as well if you specify two integers. The Ribbon will try to show the large icon if that is possible. Take a look:

Adding the group to the Quick Access is also possible. The controls will remain grayed out if using them is not possible. The ribbon controls will inherit the traits of the control in the case of the toolbar. You do not need to write any more code. Just add it to the ribbon and observe that it works!

We can also add check boxes. We will transform the view menu section to the ribbon to demonstrate this. This can be handy if you want to show or hide the Statusbar or the toolbar:

// // Create and add a "View" group (panel):

CMFCRibbonPanel* pPanelView =

pCategoryGeneral->AddPanel (_T ("View"), m_PanelImages.ExtractIcon (7));

 

//Add members

pPanelView->Add (new CMFCRibbonCheckBox (ID_VIEW_STATUS_BAR,

_T ("Status bar")));

 

pPanelView->Add (new CMFCRibbonCheckBox (

ID_VIEW_TOOLBAR, _T ("Toolbar")));

 

Following the same guidelines, we can add a window management section as well (as you can see from the image above, I already did so). We will first add a button to which we assign a large image. Afterward we will add sub items to this to create menu-like behavior.

 

// Add a panel to control the display of MDI windows

CMFCRibbonPanel* pPanelWindow = pCategoryGeneral->AddPanel (_T ("Window"), m_PanelImages.ExtractIcon (0));

 

CMFCRibbonButton* pBtnWindows = new CMFCRibbonButton (0, _T ("Windowsnw"), -1, 1);

 

pBtnWindows->AddSubItem (new CMFCRibbonButton (ID_WINDOW_NEW, _T ("New Window"), -1, -1), -1);

pBtnWindows->AddSubItem (new CMFCRibbonButton (ID_WINDOW_CASCADE, _T ("Cascade"), -1, -1), -1);

pBtnWindows->AddSubItem (new CMFCRibbonButton (

ID_WINDOW_TILE_HORZ, _T ("Tile"), -1, -1), -1);

pPanelWindow->Add (pBtnWindows);

 

If you do not want to display any icon/image for an item, you can pass as an argument minus one. For reasons of completeness I also added a new help category. For this, I included a help link and an about button. The code is straightforward:

CMFCRibbonPanel* pPanelHelp = pCategoryGeneral->AddPanel (

_T ("Help"),

m_PanelImages.ExtractIcon (12));

pPanelHelp->Add (new CMFCRibbonButton (ID_HELP_FINDER, _T ("Help Topics"), 12));

pPanelHelp->Add (new CMFCRibbonButton (ID_APP_ABOUT, _T (

"About XML Tree Viewer..."), 13));

 

 

If for some reason you failed to follow the coding part, here is my final version:

 

I would like to express my appreciation towards you for reading to the end this article. Please enter any questions you may have to the blog commenting section that you can find below or join our friendly site over at DevHardware or DevArticles and tell us your thoughts/problems there. I would also like to ask you to rate my article accordingly. This article was intended more to be a teaser to the world of the Ribbon. I plan to write more articles on this topic that are more detailed. Therefore, If you are interested, remember to check back from time to time. Live With Passion!

blog comments powered by Disqus
.NET ARTICLES

- .Net 4.5 Brings Changes
- Understanding Events in VB.NET
- Objects, Properties, Events and Methods in V...
- Install Visual Web Developer Express 2010
- Microsoft Gadgeteer an Open Source Alternati...
- Best DotNetNuke Modules
- Facebook Image Viewer in Visual Basic
- Murach`s ADO.NET 4 Database Programming with...
- 5 Must Have Visual Studio 2010 Extensions
- Dynamic Web Applications with ASP.NET Mono u...
- PDFSharp: HTML to PDF in ASP.NET 3.5 using V...
- Using the PDFSharp Library in ASP.NET 3.5 wi...
- Sending Email in ASP.NET 3.5 using VB.NET wi...
- ASP.NET 3.5 Role Based Security and User Aut...
- Creating ASP.NET Login Web Pages and Basic C...

ASP Web Hosting ASP.Net Web Hosting Windows Web Hosting
 
 
 

ASP Free Forums 
 RSS  Tutorials RSS
 RSS  Forums RSS
 RSS  All Feeds
Site Map 
Request Media Kit
Write For Us Get Paid 
Weekly Newsletter
 
Developer Updates  
Free Website Content 
Privacy Policy 
Support 


© 2003-2012 by Developer Shed. All rights reserved. DS Cluster 7 - Follow our Sitemap
Most Popular Topics
All ASP.Net Tutorials