Click here to Skip to main content
15,879,096 members
Articles / Programming Languages / C++/CLI
Article

Using the Windows Forms 2.0 MenuStrip and ToolStrip controls to give your MFC applications a new look and feel

Rate me:
Please Sign up or sign in to vote.
4.84/5 (22 votes)
21 Feb 2006CPOL2 min read 142.2K   2.5K   39   15
This article demonstrates how to use the Windows Forms 2.0 MenuStrip and ToolStrip controls in an MFC SDI application, using C++/CLI, to get the Office 2003 style menu and toolbar

Image 1

Introduction

In this article, I'll demonstrate how to use the Windows Forms 2.0 MenuStrip and ToolStrip controls in an MFC SDI application, using C++/CLI, to get the Office 2003 style menu and toolbar. I assume that you already know how to use these new Forms controls introduced in Whidbey, that you are familiar with C++/CLI syntax, and that you know about the new Windows Forms interop helper classes that have been added to MFC 8.

Step-by-step guide

This is a step by step guide to adding the Forms controls to an existing application. For the example, just use a default SDI app that's generated by VC++ 8. Note that, the same techniques can be more or less used the same way for an MDI application too - except you need to change the classes used accordingly.

Step 1 : Remove the MFC toolbar creation code

Comment out or delete the MFC toolbar creation code, and any references to it. For a default app, the following lines are to be commented out (or removed).

MC++
//if (!m_wndToolBar.CreateEx(this, 
//  TBSTYLE_FLAT, WS_CHILD | WS_VISIBLE | CBRS_TOP
//  | CBRS_GRIPPER | CBRS_TOOLTIPS | CBRS_FLYBY | 
//  CBRS_SIZE_DYNAMIC) ||
//  !m_wndToolBar.LoadToolBar(IDR_MAINFRAME))
//{
//  TRACE0("Failed to create toolbar\n");
//  return -1; // fail to create
//}

//m_wndToolBar.EnableDocking(CBRS_ALIGN_ANY);
//DockControlBar(&m_wndToolBar);

Step 2 : Destroy the MFC menu

You can do this in PreCreateWindow, but for this example, out of personal choice, we'll do this in

MC++
OnCreate 
- very early on. The idea is that you can do the same thing if you want to swap the MFC menu for the Forms menu, in response to a user action.

MC++
int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
    if (CFrameWnd::OnCreate(lpCreateStruct) == -1)
        return -1;

    GetMenu()->DestroyMenu();
    SetMenu(NULL);

Step 3 : Add MenuStrip and ToolStrip members to the frame window class

We use the CWinFormsControl which provides functionality to host a Forms control in MFC.

MC++
CWinFormsControl<System::Windows::Forms::MenuStrip> m_MenuStrip;
CWinFormsControl<System::Windows::Forms::ToolStrip> m_ToolStrip;

Step 4 : Create and initialize the MenuStrip and ToolStrip controls

We do this in OnCreate. The code below shows what I've done, and there are a few comments explaining what's being done. It's mostly standard Windows Forms code in there.

MC++
using namespace System::Windows::Forms;

//Create the Forms controls and set the frame window as parent
m_MenuStrip.CreateManagedControl(WS_VISIBLE|WS_CHILD, 
    CRect(0,0,0,25),this, 1001);
m_ToolStrip.CreateManagedControl(WS_VISIBLE|WS_CHILD, 
    CRect(0,25,0,75),this, 1002);

//Create and initialize the menu strip

ToolStripMenuItem^ topitem = gcnew ToolStripMenuItem();
ToolStripMenuItem^ item = gcnew ToolStripMenuItem();

topitem->Text = "File";
m_MenuStrip->Items->Add(topitem); 

item->Text = "Open";
//We load the icon using LoadImage, and convert the HICON
//to a Bitmap using the FromHicon method. LoadImage was
//preferred to support higher color icons. The CWinApp LoadIcon
//isn't as flexible or functional, and always treats icons as 32x32.
item->Image = System::Drawing::Bitmap::FromHicon((System::IntPtr)
    LoadImage(AfxGetInstanceHandle(),MAKEINTRESOURCE(IDI_OPEN),
    IMAGE_ICON,0,0,LR_DEFAULTCOLOR));
//Maps the C++ class method to the event handler
item->Click += MAKE_DELEGATE(System::EventHandler,File_Open_Click);

topitem->DropDownItems->Add(item);

item = gcnew ToolStripMenuItem();
item->Text = "Exit";
item->Image = System::Drawing::Bitmap::FromHicon((System::IntPtr)
    LoadImage(AfxGetInstanceHandle(),MAKEINTRESOURCE(IDI_EXIT),
    IMAGE_ICON,0,0,LR_DEFAULTCOLOR));
item->Click += MAKE_DELEGATE(System::EventHandler,File_Exit_Click);

topitem->DropDownItems->Add(item);

topitem = gcnew ToolStripMenuItem();
topitem->Text = "Help";
m_MenuStrip->Items->Add(topitem);

item = gcnew ToolStripMenuItem();
item->Text = "About";
item->Image = System::Drawing::Bitmap::FromHicon((System::IntPtr)
    LoadImage(AfxGetInstanceHandle(),MAKEINTRESOURCE(IDI_HELP),
    IMAGE_ICON,0,0,LR_DEFAULTCOLOR));
item->Click += MAKE_DELEGATE(System::EventHandler,Help_About_Click);

topitem->DropDownItems->Add(item);

//Create and initialize the tool strip

ToolStripButton^ tbutton;

tbutton = gcnew ToolStripButton();
tbutton->Size = System::Drawing::Size(50,50);
tbutton->Text = "Open";
tbutton->TextAlign = System::Drawing::ContentAlignment::BottomCenter;
tbutton->ToolTipText = tbutton->Text; 
tbutton->Image = System::Drawing::Bitmap::FromHicon((System::IntPtr)
    LoadImage(AfxGetInstanceHandle(),MAKEINTRESOURCE(IDI_OPEN),
    IMAGE_ICON,0,0,LR_DEFAULTCOLOR));
tbutton->ImageScaling = ToolStripItemImageScaling::None;
tbutton->ImageTransparentColor = 
    System::Drawing::Color::FromArgb(220,220,220);
tbutton->ImageAlign = System::Drawing::ContentAlignment::TopCenter;
tbutton->TextImageRelation = TextImageRelation::ImageAboveText;
tbutton->Click += MAKE_DELEGATE(System::EventHandler,File_Open_Click);
tbutton->Padding = Padding(5,0,5,0);

m_ToolStrip->Items->Add(tbutton);

tbutton = gcnew ToolStripButton();
tbutton->Size = System::Drawing::Size(50,50);
tbutton->Text = "About";
tbutton->TextAlign = System::Drawing::ContentAlignment::BottomCenter;
tbutton->ToolTipText = tbutton->Text;
tbutton->Image = System::Drawing::Bitmap::FromHicon((System::IntPtr)
    LoadImage(AfxGetInstanceHandle(),MAKEINTRESOURCE(IDI_HELP),
    IMAGE_ICON,0,0,LR_DEFAULTCOLOR));
tbutton->ImageScaling = ToolStripItemImageScaling::None;
tbutton->ImageTransparentColor = 
    System::Drawing::Color::FromArgb(220,220,220);
tbutton->ImageAlign = System::Drawing::ContentAlignment::TopCenter;
tbutton->TextImageRelation = TextImageRelation::ImageAboveText;
tbutton->Click += MAKE_DELEGATE(System::EventHandler,Help_About_Click);
tbutton->Padding = Padding(5,0,5,0);

m_ToolStrip->Items->Add(tbutton);

tbutton = gcnew ToolStripButton();
tbutton->Size = System::Drawing::Size(50,50);
tbutton->Text = "Exit";
tbutton->TextAlign = System::Drawing::ContentAlignment::BottomCenter;
tbutton->ToolTipText = tbutton->Text;
tbutton->Image = System::Drawing::Bitmap::FromHicon((System::IntPtr)
    LoadImage(AfxGetInstanceHandle(),MAKEINTRESOURCE(IDI_EXIT),
    IMAGE_ICON,0,0,LR_DEFAULTCOLOR));
tbutton->ImageScaling = ToolStripItemImageScaling::None;
tbutton->ImageTransparentColor = 
    System::Drawing::Color::FromArgb(220,220,220);
tbutton->ImageAlign = System::Drawing::ContentAlignment::TopCenter;
tbutton->TextImageRelation = TextImageRelation::ImageAboveText;
tbutton->Click += MAKE_DELEGATE(System::EventHandler,File_Exit_Click);
tbutton->Padding = Padding(5,0,5,0);

m_ToolStrip->Items->Add(tbutton);

Step 5 : Handle OnSize in your frame window

We need to prevent the view window from showing itself on top of the menu strip and the tool strip controls we have added. This is done on OnSize.

MC++
void CMainFrame::OnSize(UINT nType, int cx, int cy)
{
    CFrameWnd::OnSize(nType, cx, cy);       

    // If the menu strip is created
    if(m_MenuStrip.GetSafeHwnd())
    {
        CRect rect;
        // Need to figure out the required rect that accounts
        // for any other control bars (like the status bar)
        RepositionBars(AFX_IDW_CONTROLBAR_FIRST,
            AFX_IDW_CONTROLBAR_LAST,0,CWnd::reposQuery,&rect);
        // Adjust rect so we have enough space to show
        // the menu and tool strips
        m_MenuStrip->Size = System::Drawing::Size(
            rect.Width(),m_MenuStrip->Size.Height);
        m_ToolStrip->Size = System::Drawing::Size(
            rect.Width(),m_ToolStrip->Size.Height);
        rect.top += (m_MenuStrip->Size.Height + 
            m_ToolStrip->Size.Height);
        CView* pView = GetActiveView();
        if(pView)
        {
            // resize the view window
            pView->MoveWindow(rect);
        }
    }
}

Step 6 : Add delegate maps

These have to be added to the public section in your class declaration. They essentially map event handlers to class methods.

MC++
BEGIN_DELEGATE_MAP( CMainFrame )
    EVENT_DELEGATE_ENTRY( File_Exit_Click, 
        System::Object^, System::EventArgs^)
    EVENT_DELEGATE_ENTRY( Help_About_Click, 
        System::Object^, System::EventArgs^)
    EVENT_DELEGATE_ENTRY( File_Open_Click, 
        System::Object^, System::EventArgs^)
END_DELEGATE_MAP()

Step 7 : Add event handlers

Just write the event handlers that are called when a tool strip button or a menu is clicked.

MC++
void CMainFrame::File_Exit_Click(System::Object^ sender,
    System::EventArgs^ e)
{
    PostMessage(WM_CLOSE);
}

void CMainFrame::File_Open_Click(System::Object^ sender, 
    System::EventArgs^ e)
{
    PostMessage(WM_COMMAND,ID_FILE_OPEN);
}

void CMainFrame::Help_About_Click(System::Object^ sender, 
    System::EventArgs^ e)
{
    ReleaseCapture(); // Needed as the ToolStrip captures the mouse
    CAboutDlg aboutDlg;
    aboutDlg.DoModal();
}

History

  • Feb 21 2006 - Fixed an issue with showing modal dialogs from a toolbar item click handler.
  • Feb 15 2006 - Article first published.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
United States United States
Nish Nishant is a technology enthusiast from Columbus, Ohio. He has over 20 years of software industry experience in various roles including Chief Technology Officer, Senior Solution Architect, Lead Software Architect, Principal Software Engineer, and Engineering/Architecture Team Leader. Nish is a 14-time recipient of the Microsoft Visual C++ MVP Award.

Nish authored C++/CLI in Action for Manning Publications in 2005, and co-authored Extending MFC Applications with the .NET Framework for Addison Wesley in 2003. In addition, he has over 140 published technology articles on CodeProject.com and another 250+ blog articles on his WordPress blog. Nish is experienced in technology leadership, solution architecture, software architecture, cloud development (AWS and Azure), REST services, software engineering best practices, CI/CD, mentoring, and directing all stages of software development.

Nish's Technology Blog : voidnish.wordpress.com

Comments and Discussions

 
GeneralMy vote of 5 Pin
csharpbd27-Aug-13 10:26
professionalcsharpbd27-Aug-13 10:26 
QuestionNice article..How to access Parent? Pin
Rajgkk3-May-07 22:33
Rajgkk3-May-07 22:33 
QuestionAccess Keys? Pin
DSmith197418-Feb-07 0:26
DSmith197418-Feb-07 0:26 
GeneralVertical Toolbar Pin
Sunil_Cool23-Jan-07 0:34
Sunil_Cool23-Jan-07 0:34 
QuestionVisual Studio.Net 2003 , mfc 7.1 ? Pin
fiversen8-Jan-07 22:27
fiversen8-Jan-07 22:27 
AnswerRe: Visual Studio.Net 2003 , mfc 7.1 ? Pin
The Cake of Deceit23-Sep-08 8:59
The Cake of Deceit23-Sep-08 8:59 
QuestionYou reduce the MFC functionality Pin
Alexey Shalnov16-May-06 23:15
Alexey Shalnov16-May-06 23:15 
GeneralMenu Access and Shortcut Keys Pin
r0nen28-Feb-06 8:48
r0nen28-Feb-06 8:48 
GeneralNice Article Pin
Majid Shahabfar21-Feb-06 23:47
Majid Shahabfar21-Feb-06 23:47 
GeneralRe: Nice Article Pin
Nish Nishant22-Feb-06 13:26
sitebuilderNish Nishant22-Feb-06 13:26 
QuestionWindows Forms Control class Problem? Pin
Mr.Sri@Hotmail21-Feb-06 10:21
Mr.Sri@Hotmail21-Feb-06 10:21 
AnswerRe: Windows Forms Control class Problem? Pin
Nish Nishant21-Feb-06 11:46
sitebuilderNish Nishant21-Feb-06 11:46 
GeneralRe: Windows Forms Control class Problem? Pin
NedoRot23-Jun-10 2:50
NedoRot23-Jun-10 2:50 
GeneralIf only I had this a month ago... Pin
oshah18-Feb-06 6:39
oshah18-Feb-06 6:39 
GeneralRe: If only I had this a month ago... Pin
Nish Nishant21-Feb-06 11:44
sitebuilderNish Nishant21-Feb-06 11:44 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.