Click here to Skip to main content
15,867,568 members
Articles / Desktop Programming / MFC

Tear-off Menus

Rate me:
Please Sign up or sign in to vote.
2.50/5 (8 votes)
4 Dec 2003CPOL3 min read 94K   2.9K   33   10
See how to have tear-off menus in your program

Introduction

Microsoft introduced a new feature some Office versions ago: Popup menus you can tear off and use as toolbars. This is a good way for the user to put important functions directly on the application workspace without opening a menu each time.

Trying to implement this feature caused a lot of problems. The easiest thing was to draw the menu so it looks like you can tear it off. The next thing was how to get the mouse movements and button pressed, which caused me to stop working on this for a long time. In the November 2003 issue of the MSDN magazine, Paul DiLascia wrote some code to display menu tooltips. With this code, it was quite easy to get it working.

Behind the Scenes

The new class CMenuTearOffManager has all the functions you need for tear-off menus. It basically maps popup menus to toolbars and handles the GUI part. Using Paul DiLascia CSubclassWnd class CMenuTearOffManager reacts on every new popup menu and checks (and modifies) it in case it has a tear-off item. Then the "caption" is calculated and painted. Let's see how it works inside: First, whenever a new popup menu is opened (WM_INITMENUPOPUP), it goes through all items and compares them to the internal map that assigns menu items to toolbars. In case this item is found, it is converted to an ownerdrawn item. For that item, WM_MEASUREITEM calculates the height for the "caption" and WM_DRAWITEM paints the caption. And here's the tricky part: during painting, a new window is created that lays above the menu item, so mouse moves an be trapped; each time you select a different menu item, the window gets invisible. The new window is not active (which would cause the menu to close), so mouse moves are captured by WM_NCHITTEST. Moving the mouse and pressing the left mouse button closes the window and forwards the message to the toolbar control - that's it!

Using the Code

First, add the CMenuTearOffManager class to the CMainFrame. In your CMainFrame::OnCreate(), add all tear-off toolbars using code like this:

C++
if (!m_wndToolBarTearOff1.CreateEx(this, TBSTYLE_FLAT, WS_CHILD 
    |WS_VISIBLE| CBRS_TOP
    | CBRS_GRIPPER | CBRS_TOOLTIPS | CBRS_FLYBY | CBRS_SIZE_DYNAMIC) ||
    !m_wndToolBarTearOff1.LoadToolBar(IDR_TEAROFF1))
{
  TRACE0("Unable to create toolbar 1\n");
  return -1;
}
m_wndToolBarTearOff1.EnableDocking(CBRS_ALIGN_ANY);
ShowControlBar(&m_wndToolBarTearOff1, FALSE, FALSE);

(The last line of code causes the toolbar to be initially invisible.)

Then, insert a new menu item on top of each popup you'd like to act as a tear-off menu (here: ID_TEAROFFDEMO_TEAROFF2). Also insert new toolbars that are displayed for the popup menus. There's no need to have the same commands on the toolbar.

After creating all toolbars, use these lines to install the class and connect it to menu items:

C++
m_menuTOManager.Install(this, this);
m_menuTOManager.AddTearOff(ID_TEAROFFDEMO_TEAROFF1, &m_wndToolBarTearOff1);
m_menuTOManager.AddTearOff(ID_TEAROFFDEMO_TEAROFF2, &m_wndToolBarTearOff2);
...

This connects the "virtual" menu item ID_TEAROFFDEMO_TEAROFF2 to the toolbar m_wndToolBarTearOff2. All the rest is done automatically.

Please see the sample how to use it. All comments are in English, only the resources are in German.

Limitations

This class has a few differences to the "original" implementation you know from e.g. Microsoft Office and some other limitations:

  • Different drawing of the tear-off caption
  • Menu closes immediately after tearing the toolbar away
  • Office products allow to doc the popup again during dragging
  • Not (yet) possible for context menus
  • Not tested for ownerdrawn menus, but it should work

Credits

Paul DiLascia for his subclass class and the menu tip manager, which helped a lot in developing this class!

History

  • 30.11.2003: Initial release

License

Feel free to use this class in any of your projects or modify it! Please keep my credits in the source.

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.

License

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


Written By
Web Developer
Germany Germany
Ok, a few words about me:

I started programming on the C64 by the "trial and error" method. Years later my parents got their first PC (Atari PC4, AT 8 MHz) where I started with Turbo Pascal. The next steps led to Turbo Pascal for Windows, Visual C++ 1.52c, and finally Visual C++ 6.

I had several chances to code larger projects, e.g.
* stand-alone disc copy station software (Win 3.1) with automatic reboot, disc encryption, ...
* government-used strategic decision system
* MLM marketing tool (www.upline.de)
* maintenance for show planning system and other TV software (www.hse24.de)

A lot of code, tipps and help came from this site for my later projects. Thanks again to all who helped me, even if they don't know it. I'm trying to share code (which is worth sharing) so others can get the help I got (and still need) for everyday problems.

Well, I think that's enough.

Comments and Discussions

 
GeneralCould some help me - can't find the bug Pin
Alexander Bischofberger10-Dec-03 20:51
Alexander Bischofberger10-Dec-03 20:51 
GeneralRe: Could some help me - can't find the bug Pin
nohoper12-May-05 20:02
nohoper12-May-05 20:02 
GeneralRe: Could some help me - can't find the bug Pin
aycarru4-Dec-10 18:01
aycarru4-Dec-10 18:01 
GeneralMe either Pin
Rafael Fernández López10-Dec-03 11:26
Rafael Fernández López10-Dec-03 11:26 
It won't run on XP


Written by: Rafael Fernández López.


void life ( bool me, bool her )
{

if ( her )
{
me = true ;
}
else
{
me = false ;
}
}

GeneralMay be a good stuff, but ... Pin
synopsislogic1-Dec-03 11:31
synopsislogic1-Dec-03 11:31 
GeneralRe: May be a good stuff, but ... Pin
Alexander Bischofberger1-Dec-03 20:55
Alexander Bischofberger1-Dec-03 20:55 
GeneralIt doesn't work (Win2k) Pin
snakeware1-Dec-03 11:10
snakeware1-Dec-03 11:10 
GeneralDoesnt appear to work on XP too Pin
CEx1-Dec-03 20:52
CEx1-Dec-03 20:52 
GeneralCode doesn't compile Pin
Grump30-Nov-03 22:17
Grump30-Nov-03 22:17 
GeneralRe: Code doesn't compile Pin
Alexander Bischofberger1-Dec-03 7:21
Alexander Bischofberger1-Dec-03 7:21 

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.