Click here to Skip to main content
15,868,016 members
Articles / Desktop Programming / MFC
Article

Radial Context Menu

Rate me:
Please Sign up or sign in to vote.
4.85/5 (26 votes)
20 Jul 20053 min read 84.7K   2.6K   52   14
Mouse gesture with a graphical user interface.

Radial Context Menu

Radial Context Menu With Tips

Radial context menu ...

... with tips

Mouse gesture with a graphical user interface.

Introduction

Some time ago, as I was looking for some kind of mouse gesture add-on for my web browser, I came across this web site. There, one can get an add-on for the browsers Firefox and Mozilla, which implements mouse gestures with a graphical front end. I was slightly confused by this fact - 'Mouse gesture with GUI?', I thought. What could this look like? I took a look at the screenshots and was immediately enthused. The add-on merged the advantages of context menus with that of mouse gestures in a clever way: fast execution of commands as with mouse gestures were combined with an easy to understand context menu. In this way one learns the often used gestures very fast while one still has access to the gestures one doesn't recall at any time. Especially less experienced users will profit from this concept. For instance, my wife and my kids won't browse the web without this extension anymore . So if you're using Firefox or Mozilla, go and get your copy of this real great extension!

I planned to implement this ingenious concept for the use with some of my projects for a long time, but had too less free time. Until now...

How it works

As soon as the user presses the right mouse button, a round menu pops up, displaying up to eight icons. The user now may move the mouse in one of eight directions. As soon as (s)he releases the right mouse button, the function below the mouse cursor will be executed. Since mouse gestures don't work precisely on pixels, the radial menu will follow the mouse cursor on demand. The cursor also doesn't need to be exactly over the icon to select a function. To find out which function to use, the menu checks all points on a thought line from the current cursor position to the center of the radial menu. If the line intersects an icon's area, then it is assumed that the user meant this icon. In this way fast acting professionals will get the right result, too. For users who are new to your program and/or can't recall every mouse gesture (or even don't know what the icon stands for), the menu pops up some kind of tool tips after a short delay time. That way even inexperienced users or users who don't like mouse gestures will quickly get along with this concept.

To build up more complex menus (with more than 8 items), one can build up submenus. That way one can implement gestures such as 'right, then up', too.

Using the code

The radial context menu is implemented to watch for the right mouse button. To activate such a menu, you will need to install a handler for the WM_RBUTTONDOWN window message. The radial context menu object can either be instantiated in this handler method, in the constructor of your CWnd-derived class, or in the OnCreate() handler method.

The size of the icons, the colors and fonts to use should be set up before one sets up the menu items themselves. By default the radial menu will use the system colors and fonts as well as an icon size of 16x16 pixels.

// methods for configuration

// Set background color.
CRadialContextMenu &    SetBkColor(COLORREF clr = ::GetSysColor(COLOR_BTNFACE));

// Set icon size.
CRadialContextMenu &    SetIconSize(CSize size = CSize(16, 16));
CRadialContextMenu &    SetIconSize(int cx, int cy);

// Set font for tips
CRadialContextMenu &    SetTipFont(CFont * pFont);

// Set colors for the tips
CRadialContextMenu &    SetTipColors(COLORREF color1, COLORREF color2, 
                           COLORREF textcolor = ::GetSysColor(COLOR_BTNTEXT));

Having set up the outwardness, one might go on to set up the menu items.

// methods for setting menu items

// Many projects support CFrameWnd or derived window classes that
// own at least one toolbar. To simplify the setup of the radial
// context menu, you might add these toolbars to the menu. You
// don't need to specify an icon then.
CRadialContextMenu &    AddToolBar(CToolBar * pBar);


// Note on CRadialContextMenu::EIconPosition:
// The enumeration describes all possible positions for icons. It starts
// with ICON_TOP und goes clockwise to ICON_TOPRIGHT,
// ICON_RIGHT, ICON_BOTTOMRIGHT and so on.

// Tip texts are always optional. Normally the menu tries to locate
// the tips by browsing the string resources for a string with the
// same ID as given as an argument.

// Use this overload only if you have provided at least one toolbar
// that contains the icons.
CRadialContextMenu &    SetMenuItem(UINT uID, EIconPosition pos, 
                               const CString & tip = "");

// Use this to provide an icon by yourself.
CRadialContextMenu &    SetMenuItem(UINT uID, HICON hIcon, 
                               EIconPosition pos, const CString & tip = "");

// Use this to set a submenu.
CRadialContextMenu &    SetMenuItem(CRadialContextMenu * pSubmenu, 
                               HICON hIcon, EIconPosition pos, 
                               const CString & tip = "");

// You might enable/disable items by either
// the command id or the position in the menu
CRadialContextMenu &    EnableMenuItem(UINT uID, bool bEnable = true);
CRadialContextMenu &    EnableMenuItem(EIconPosition pos, bool bEnable = true);

Now one might call this method.

bool TrackRadialMenu(CWnd * pReceiver);

to pop up the radial context menu. The method won't return unless the user releases the right mouse button or presses the ESC key. The return value indicates whether the user selected a valid item. If it returns true, then a WM_COMMAND message was sent to the window given as the argument.

Thus an exemplary implementation of a WM_RBUTTONDOWN handler might look like this:

void CMyOwnWindow::OnRButtonDown(UINT nFlags, CPoint point)
{
    // In this small example we use standard colors and
    // standard icon size and font.
    CRadialContextMenu()
        .AddToolBar(&m_wndToolbar)
        .SetMenuItem(ID_FILE_NEW, CRadialContextMenu::ICON_TOP)
        .SetMenuItem(ID_FILE_OPEN, CRadialContextMenu::ICON_RIGHT)
        .SetMenuItem(ID_FILE_SAVE, CRadialContextMenu::ICON_BOTTOM)
        .SetMenuItem(ID_FILE_PRINT, CRadialContextMenu::ICON_LEFT)
        .EnableMenuItem(ID_FILE_SAVE, GetDocument()->IsModified())
        .TrackRadialMenu(this);
}

History

  • July, 20 2005 - first implementation.

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


Written By
Germany Germany
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
Generalvery useful Pin
Southmountain3-Feb-20 19:08
Southmountain3-Feb-20 19:08 
Generalcool Pin
Bartosz Wójcik28-Feb-08 5:29
Bartosz Wójcik28-Feb-08 5:29 
GeneralPie Menus Pin
bmz5-Aug-05 20:40
bmz5-Aug-05 20:40 
GeneralC# Pin
dr4cul421-Jul-05 21:27
dr4cul421-Jul-05 21:27 
GeneralRe: C# Pin
Yves Tkaczyk22-Jul-05 4:06
Yves Tkaczyk22-Jul-05 4:06 
GeneralRe: C# Pin
Tim8w5-Feb-21 8:12
Tim8w5-Feb-21 8:12 
GeneralRe: C# Pin
Yves Tkaczyk5-Feb-21 9:49
Yves Tkaczyk5-Feb-21 9:49 
GeneralFirst impressions Pin
Neville Franks21-Jul-05 0:17
Neville Franks21-Jul-05 0:17 
GeneralRe: First impressions Pin
Nish Nishant21-Jul-05 1:47
sitebuilderNish Nishant21-Jul-05 1:47 
GeneralRe: First impressions Pin
Kochise21-Jul-05 2:27
Kochise21-Jul-05 2:27 
GeneralRe: First impressions Pin
Joerg Koenig21-Jul-05 2:30
Joerg Koenig21-Jul-05 2:30 
With a mousepad you'll need exactly two fingers: one to hold down the right mouse button und one to move the cursor.
But I agree - mouse gestures aren't everybody's taste. Smile | :)
A serious application might be configurable to either use mouse gestures or traditional context menus...
GeneralRe: First impressions Pin
Schniddel21-Jul-05 9:56
Schniddel21-Jul-05 9:56 
GeneralRe: First impressions Pin
Dieter Hammer21-Jul-05 20:03
Dieter Hammer21-Jul-05 20:03 
GeneralRe: First impressions Pin
Andromeda Shun26-Jul-05 21:33
Andromeda Shun26-Jul-05 21:33 

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.