Click here to Skip to main content
Click here to Skip to main content

Upgrading from MainMenu and ToolBar to MenuStrip and ToolStrip

, 26 Feb 2006
Rate this:
Please Sign up or sign in to vote.
Step-by-step guide to upgrading menus and toolbars to NET 2.0 and code for improving the user interface.
Sample Image - ToolStripEx.jpg

Introduction

In the 2.0 version of the .NET Framework the support for menus and toolbars has been upgraded. Unfortunately the structure of each new class has changed dramatically and conversion is not trivial. Also, the user interface exhibits some unexpected behavior. This article gives some tips for making the conversion from the old to the new. It also introduces simple extensions to the ToolStrip and MenuStrip classes that allow customization of mouseover highlighting and implementation of "Click Through" to improve the user interface.

Background

Like me, you probably have some legacy code written for the 1.x versions of the .NET Framework that you would like to upgrade to the fancier menus and toolbars that are available in the latest version. The MainMenu and ContextMenu classes have been replaced with entirely new classes, MenuStrip and ContextMenuStrip. Likewise, the ToolBar class has been replaced with ToolStrip. The new classes have a more up-to-date appearance and can be extended in new ways. For example, you can easily put ComboBoxes in menus or progress bars in a ToolStrip or StatusStrip. Since the structures of the new classes are quite different, it is not entirely straightforward to upgrade the old controls. I searched the Internet in vain for a simple process to follow. In the end I decided to take notes on what I had to do and share it with the Code Project community.

Having gone through the trouble of making the conversion, you may discover that the new controls behave in a fashion you did not expect, which might not be to your taste. There are two issues. First, unlike most Windows applications, the buttons and menus do not respond to a single click when their parent form does not have focus. Instead, you must click on the control twice before it responds, once to activate the form and the second time to activate the control. This is a perfectly fine model for the user interface and is the way Office 2003 and Visual Studio 2005 work. However, it would be better if the user could choose this model or the more standard approach in which a single click activates the control. Also, the new controls have a "feature" (I'm trying to be kind) that is very confusing to me. Unlike Office 2003, ToolStrip or MenuStrip will still show a highlight when the mouse moves over them on an inactive form. To me, this means they are ready for action, but unfortunately they still require a second click.

Borrowing code from Rick Brewster, I have extended the ToolStrip and MenuStrip classes to implement a feature that allows a single click to activate the control. For those who prefer the Office 2003 user interface, I have also implemented a "Suppress Highlighting" feature to enable mouseover highlighting only when the parent form (or one of its children) is active. I have included the code and a sample application to demonstrate the behavior of these new classes.

Upgrading by search and replace

If you are writing a new application, there should be no problem creating new MenuStrips and ToolStrips using the Visual Studio designer. However, if you are upgrading code, it is a large task to recreate all of your old menus and toolbars in the designer. If you use search and replace, it is not obvious how to proceed and mistakes are easily made. My goal is to save you some time by providing a step-by-step guide to the major changes. It won't cover every possibility, so you may have to correct some things after an initial compilation.

First, I strongly encourage you to save a backup of your entire project before you start editing. It is always dangerous to manually change the code created by the designer. If you make a mistake or if my tips lead you astray, you could easily end up with code that the designer cannot interpret, locking you out of the ability to modify your form until the bugs have been found. Second, the new class structures are complex, so my suggestions may only get you started. My suggestion is to charge forward with the simple changes listed here, then if the compiler complains, resolve any remaining issues.

I will assume you are using Visual Studio to edit your code. Open the code view and close the design view for the form you are upgrading. Follow these tips in order, using the bold highlighted text as your search and replace strings. Select the options to "Match Case", "Search Hidden Text", and search the "Current Document". Do the replacements one item at a time, checking to be sure each one makes sense in the context.

Tips for upgrading to MenuStrip and ContextMenuStrip

  1. Replace MainMenu with MenuStrip
  2. Replace ContextMenu with ContextMenuStrip
  3. If the MainMenu constructor or ContextMenu constructor has an argument, remove it
  4. Replace Menu.GetMainMenu() with ToolStripItem.GetCurrentParent(), the return value is a ToolStrip, which you may need to explicitly typecast to MenuStrip
  5. Replace MenuStrip.MenuItems and ContextMenuStrip.MenuItems with MenuStrip.Items or ContextMenuStrip.Items, but be sure you are only doing this on MenuStrip or ContextMenuStrip items and not on MenuItems
  6. Replace MenuItem.MenuItems with ToolStripMenuItem.DropDownItems
  7. Replace this.Menu with this.MainMenuStrip
  8. Replace MenuItem with ToolStripMenuItem (and MenuItems with ToolStripMenuItems)
  9. Change all ToolStripMenuItem.Index properties to ToolStripMenuItem.MergeIndex
  10. Replace ToolStripMenuItem.Popup event with ToolStripDropDownItem.DropDownOpening event and ContextMenuStrip.Popop event with ContextMenuItem.Opened event.
  11. Delete lines setting the MenuItem.Shortcut property and reset these later in the designer, or edit the line to set the ToolStripMenuItem.ShortcutKeys property using the Form.Keys enumeration
  12. Replace ToolStripMenuItem.ShowShortcut with ToolStripMenuItem.ShowShortcutKeys
  13. Delete lines setting the ToolStripMenuItem.MergeOrder property
  14. Delete lines setting theToolStripMenuItem.RadioCheck property
  15. Delete lines setting the ToolStripMenuItem.MdiList property
  16. If mnMdiList is the name of the MenuItem that you want to display the list of MDI child forms, set this. MainMenuStrip.MdiWindowListItem = this.mnMdiList
  17. Find the section of the InitializeComponent() method with lines containing this.Controls.Add. If the name of your MenuStrip is mainMenu, add the following line to the method: this.Controls.Add(this.mainMenu);
  18. Now compile your code. You may find errors. If so, consult the class reference to resolve any remaining issues
  19. View your form in the designer. If all goes well, you will see your new menus. Readjust the layout to accommodate the different size of the new menu.
  20. Set any shortcut keys that were not edited in step 11.
  21. All separators will appear as menu items containing a single hyphen. Right-click on these in the designer, select "Convert to" and replace with a real separator
  22. Compile your application and see if it runs!

Tips for upgrading to ToolStrip

  1. Replace ToolBar with ToolStrip
  2. Replace ToolBarButton with ToolStripButton
  3. Replace ToolBarSeparator with ToolStripSeparator
  4. Delete lines setting ToolStrip.ButtonSize, ToolStrip.DropDownArrows, or ToolStrip.ShowToolTips, these properties don't exist for ToolStrip
  5. Replace the ToolStrip.ButtonClick event handler with separate handlers for each ToolStripButtonClick event
  6. Eliminate lines that set ToolStripButton.Style
  7. Replace ToolStripButton.Pushed with ToolStripButton.Checked
  8. Replace ToolStrip.Buttons.AddRange() with ToolStrip.Items.AddRange()
  9. Use the designer to replace all the images for the buttons. The ImageList property still works, but it has been deprecated and cannot be used within the designer
  10. Cross your fingers, compile, and run

Extending the ToolStrip and MenuStrip classes

As I mentioned above, I wanted to change the behavior of these controls to create a user interface that was more intuitive. I found most of the solution in Rick Brewster's blog on MSDN. Rick introduces a ClickThrough property and overrides the WndProc() method to watch for the WM_MOUSEACTIVATE message and change the return result from "Activate and Eat" to "Activate" when ClickThrough is true. In an MSDN forum, I found JasonD's suggestion to suppress the unwanted highlighting when click through is not occurring. He suggests overriding WndProc() to intercept the WM_MOUSEMOVE message and throw it away unless the parent form or one of its children has the focus.

I combined both of these ideas to create ToolStripEx and MenuStripEx classes. The sample project contains the code and an example of their use. Both classes contain two new properties that can be manipulated in code or set in the Visual Studio designer. They are:

// If true, activate control on a single click,
// even if the control's form does not have focus
public bool ClickThrough=false;

// If true, do not show mouseover highlighting
// unless the control's form has focus
public bool SuppressHighlighting=false;

Please refer to the sample project for the details and run the sample application to observe the effects. When you run it, try all four variations and see how the menus and toolbars respond both when the main form has the focus and when the smaller form has the focus. The code inside the ToolStripEx and MenuStripEx classes is identical, it simply defines the two properties above and then implements this simple WndProc() method:

protected override void WndProc(ref Message m)
{
    // If we don't want highlighting, throw away mousemove commands
    // when the parent form or one of its children does not have the focus
    if(m.Msg == WinConst.WM_MOUSEMOVE && this.suppressHighlighting &&
        !this.TopLevelControl.ContainsFocus)
            return;
    else
        base.WndProc(ref m);

    // If we want ClickThrough, replace "Activate and Eat" with
    // "Activate" on WM_MOUSEACTIVATE messages
    if(m.Msg == WinConst.WM_MOUSEACTIVATE && this.clickThrough &&
        m.Result == (IntPtr)WinConst.MA_ACTIVATEANDEAT)
            m.Result = (IntPtr)WinConst.MA_ACTIVATE;
}

Once you build the sample application, you can easily include the extended classes in your own projects, drop them onto your forms like any of the built-in classes, and edit them in the designer.

Final Thoughts

Many thanks to Rick Brewster and JasonD for providing code and suggestions for how to obtain the desired user interface behavior.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here

Share

About the Author

Jim Hollenhorst
Researcher
United States United States
Ultrapico Website: http://www.ultrapico.com
 
Download Expresso 3.0, the latest version of the award-winning regular expression development tool.

Comments and Discussions

 
GeneralMy vote of 5 PinmemberNeonMika21-May-13 23:59 
GeneralThanks PinmemberNeolisk27-Sep-12 6:11 
GeneralRe: Thanks PinmemberJim Hollenhorst27-Sep-12 16:39 
GeneralGreat Job PinmemberCode Artist30-May-12 22:03 
GeneralMy vote of 5 Pinmembermicahtan2-Mar-12 5:44 
QuestionClickThrough! Thanks PinmemberKobus du Bruyn20-Dec-11 7:49 
GeneralMany thanks, and an addition PinmemberJamesParsons30-Nov-11 13:03 
GeneralNullReferenceException when using in Interop Toolkit 2.1 PinmemberMember 314648324-May-10 5:58 
GeneralRe: NullReferenceException when using in Interop Toolkit 2.1 PinmemberJim Hollenhorst29-May-10 6:09 
GeneralBroken Form Editor Pinmemberucflaura5-Apr-10 11:29 
GeneralRe: Broken Form Editor PinmemberJim Hollenhorst5-Apr-10 18:18 
GeneralRe: Broken Form Editor Pinmemberucflaura6-Apr-10 7:35 
GeneralRe: Broken Form Editor PinmemberJim Hollenhorst6-Apr-10 17:28 
GeneralRe: Broken Form Editor Pinmemberucflaura7-Apr-10 7:53 
GeneralExcellent Pinmembersirdan6922-Feb-10 12:53 
Thanks for this. Works perfectly.
GeneralRe: Excellent PinmemberJim Hollenhorst22-Feb-10 16:27 
Questionenable a ToolStripButton on Parent form from Child form ? Pinmemberalomylife27-Jun-08 21:48 
GeneralProblem Pinmemberalan9327-Sep-07 10:39 
GeneralVery Nice! Pinmembergirm27-Sep-07 1:35 
GeneralVery helpful! Pinmemberbarrd26-Jul-07 15:53 
QuestionChange the check image Pinmemberdanbenedek11-Jul-07 21:12 
AnswerRe: Change the check image PinmemberJim Hollenhorst11-Jul-07 21:47 
GeneralRe: Change the check image Pinmemberdanbenedek11-Jul-07 22:07 
QuestionScrolling MenuStrip PinmemberGareth Moore21-Feb-07 18:41 
GeneralThanks! Pinmembervasacheh16-Jan-07 10:51 

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

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

| Advertise | Privacy | Terms of Use | Mobile
Web01 | 2.8.141216.1 | Last Updated 26 Feb 2006
Article Copyright 2006 by Jim Hollenhorst
Everything else Copyright © CodeProject, 1999-2014
Layout: fixed | fluid