Changes to MFC in Microsoft Visual Studio 2010

In the previous articles in this series I’ve wrote about the changes in the build system, IntelliSense and browsing, and C++ compiler.
In this article I will write about the changes to MFC or the IDE in relation to MFC: new MFC toolbar controls, task dialog support, restart manager support and the ribbon designer.

New Toolbar Controls

A couple of years ago when the MFC Feature Pack (later distributed with Visual Studio 2008 SP1 and renamed as VC++ Feature Pack) was released it come with classes for new controls, some of them controls introduced in Windows Vista.
However, the IDE did not support using these new controls with the resource editor. Developers had to create everything manually, during runtime.
The new Visual Studio offers support for these controls in the resource editor. They can be used just like any other controls. However, not all the properties of these controls can be set from the Properties window. Some of them still require explicit coding.

Here is the list of the controls, the class that implement the controls and a short description of the controls:

  • Color button (CMFCColorButton): represent a color picker control allowing users to select a color
  • Font combo box (CMFCFontComboBox) : represent a combo control that displays a list of fonts available in the system
  • Edit browse (CMFCEditBrowseCtrl): an editable control with a button that displays a dialog for selecting a file or a folder
  • Visual Studio list box (CVSListBox): an editable list box with buttons for adding, removing or rearranging items in the list
  • Masked edit (CMFCMaskedEdit): a masked edit control that has a string template representing the structure of the allowed input, which is validated against the value provided by the user
  • Menu button (CMFCMenuButton): displays a pop-up menu (from a menu resource) and reports the command selected by the user
  • Property grid (CMFCPropertyGridCtrl): an editable property grid control
  • Shell list (CMFCShellListCtrl): a list control that displays the files and folders from you system just list Windows Explorer list view does
  • Shell tree (CMFCShellTreeCtrl): a tree control that displays the folder from your system just like the Windows Explorer folder view does
  • Link control (CMFCLinkCtrl): is a special button that has the appearance of a hyperlink and invokes the target link when pressed

The following images shows a dialog with these controls.

Task Dialog

One new feature introduced with Windows Vista (and available on all the following operating systems) was the task dialog. This is a replacement for the classic dialog box.
This new dialog can display command links, customized buttons, icons, and a footer with an icon (optionally) and text.

The class that implements this dialog is called CTaskDialog and is available in header <afxtaskdialog.h>. It is neither a CDialog nor a CWnd derived class; it’s actually derived from CObject.
The task dialog is only supported for UNICODE builds, and only on operating systems newer that Vista. This is enforced with #error directives in the header file.

#if !defined(_UNICODE) // Unicode required
#error CTaskDialog requires _UNICODE to be defined.
#endif

#if (NTDDI_VERSION < NTDDI_VISTA) // min Windows Vista required
#error CTaskDialog is not supported on Windows versions prior to Vista.
#endif

To check whether the task is available on the running operating system call IsSupported() method that returns TRUE if the dialog is supported and FALSE otherwise.

CString strMessage("Do you want to save your changes to the document?");
CString strDialogTitle("Save document");
CString strMainInstruction("Save document options");

CString expandedLabel("Hide extra information");
CString collapsedLabel("Show extra information");
CString expansionInfo("You can select to save your document either as XML or binary. You should prefer to save as XML as this is the new standard format.");

if (CTaskDialog::IsSupported())
{
   CTaskDialog taskDialog(strMessage, strMainInstruction, strDialogTitle, TDCBF_OK_BUTTON);
   taskDialog.SetMainIcon(TD_INFORMATION_ICON);

   taskDialog.SetCommonButtons(TDCBF_NO_BUTTON | TDCBF_CANCEL_BUTTON);
   taskDialog.LoadCommandControls(IDS_SAVE_OPTION1, IDS_SAVE_OPTION2);
   taskDialog.SetExpansionArea(expansionInfo, collapsedLabel, expandedLabel);
   taskDialog.SetFooterText(L"Note: If you don't chose to save your changes will be lost.");
   taskDialog.SetVerificationCheckboxText(L"Remember your selection");

   INT_PTR result = taskDialog.DoModal();

   if (taskDialog.GetVerificationCheckboxState() )
   {
      // PROCESS IF the user selects the verification checkbox
   }

   switch (result)
   {
      case IDS_SAVE_OPTION1:
         AfxMessageBox(L"You chose to save as XML");
         break;
      case IDS_SAVE_OPTION2:
         AfxMessageBox(L"You chose to save as binary");
         break;
      case IDNO:
         AfxMessageBox(L"You chose not to save");
         break;
      case IDCANCEL:
         AfxMessageBox(L"You chose to cancel");
         break;
      default:
         // this case should not be hit
         ASSERT(FALSE);
         break;
   }

}
else
{
   AfxMessageBox(strMessage);
}

The task dialog displayed by running the above code looks like this (on Windows 7):

It is possible to instantiate a task dialog without creating a CTaskDialog object and calling DoModal(). The class features a static method called ShowDialog() that does basically the same (not so much configurable).

INT_PTR result = CTaskDialog::ShowDialog(
   L"Do you want to save your changes to the document?",
   L"Save document options",
   L"Save document",
   IDS_SAVE_OPTION1,
   IDS_SAVE_OPTION2,
   TDCBF_NO_BUTTON | TDCBF_CANCEL_BUTTON,
   TDF_ENABLE_HYPERLINKS | TDF_USE_COMMAND_LINKS,
   L"Note: If you don't chose to save your changes will be lost.");

In these examples IDS_SAVE_OPTION1 (“Save in XML based format”) and IDS_SAVE_OPTION2 (“Save in binary format (old version)”) are two strings defined in the string table from the Resource editor.

Restart Manager

Another feature introduced with Windows Vista and that has now support in MFC is the restart manager. This is used to restart an application in case of a crash or when automatic updates are installed.

You can specify that you want support for the restart manager when you create an application.

There are several options available, all introduced with a flag defined in afxwin.h:

  • Support Restart Manager (AFX_RESTART_MANAGER_SUPPORT_RESTART): restarts after crash or upgrade
  • Reopen previously open documents (AFX_RESTART_MANAGER_SUPPORT_RESTART_ASPECTS): reopens previously open documents
  • Support application recovery (AFX_RESTART_MANAGER_SUPPORT_ALL_ASPECTS): recovers auto saved documents

The entire support is added with a single line of code. Class CWinApp has a member called m_dwRestartManagerSupportFlags, that stores the flags for the restart options. Setting this variable to the appropriate value is all that is necessary.

CRestartManagerDemoApp::CRestartManagerDemoApp()
{
   m_bHiColorIcons = TRUE;

   // support Restart Manager
   m_dwRestartManagerSupportFlags = AFX_RESTART_MANAGER_SUPPORT_ALL_ASPECTS;
}

Restarting after a crash happens only if the application was running for at least 60 seconds. This is done for preventing cyclic restarts. The following image shows the application with an unsaved document restarting:

After restart the document is empty. Since it was not saved it could not be saved. The next image shows the application restarted after a crash, but with the document saved.

Even with document recovery, auto save interval is set to 5 minutes. That means documents are saved only every 5 minutes, and if a crash happens before that interval it cannot be restored. But the interval time can be adjusted to any value. This can be done in the InitInstance() method:

CDataRecoveryHandler* autohandler = AfxGetApp()->GetDataRecoveryHandler();
autohandler->SetAutosaveInterval(60000);

The options for restarting the application and saving and loading the application data (documents) are exposed through virtual methods in the CWinAppEx class. You can override these methods in your application for custom handling of the save and load operations.

virtual void PreLoadState() {}    // called before anything is loaded
virtual void LoadCustomState() {} // called after everything is loaded
virtual void PreSaveState() {}    // called before anything is saved
virtual void SaveCustomState() {} // called after everything is saved

For customizing MFC document recovery you could read this article by Nick Wienholt.

Ribbon Designer

Another feature that was introduced with VC++ Feature Pack was the Office Fluent Ribbon. The problem was that there was no support for a ribbon designer. You had to create the entire ribbon manually.
Visual Studio 2010 now comes with a ribbon designer. You can choose whether to use a ribbon or a classical menu and toolbar when you create an application.

The ribbon created by default is minimal; it has a Home category and two panels with several commands.

The ribbon can be opened from the resource editor. There is a new category called Ribbon. By default the ribbon resource is called IDR_RIBBON. The description of the ribbon is kept in an XML file called ribbon.mfcribbon-ms, located in the res folder.

The toolbar shows only the controls available for the ribbon when a ribbon is opened in designer.

The ribbon supports several Office 2007 and Windows 7 styles.

The designer provides support for quick testing of the ribbon. On the Ribbon Editor toolbar there is a button called Test Ribbon that opens window with the ribbon. You can quickly see how it will look in the application, however, the commands are not available; clicking on the ribbon commands does not have any effect.

References

For more information also see:

More by Author

Get the Free Newsletter!

Subscribe to Developer Insider for top news, trends & analysis

Must Read