Simple IE-like Menu and Toolbar

1 Overview

This article was inspired by the Alpha WTL Sample application that I saw recently. I decided to do something similar, using the MFC library. Standard MFC applications are very out of date with their 16 colored toolbars and menus without images. There are some MFC extensions that implement Office- or Visual Studio-like control bars. They are pretty and very powerful, but just too complicated for most simple applications. Besides, they don't obey the standard Windows UI style. My idea was to create a simple interface based on Internet Explorer that implements features introduced in Windows XP and remains compatible with all OS versions since Windows 98.

The project consists of three classes:

CMenuBar: A toolbar that looks and acts exactly like a menu bar. It can be placed in a rebar control just like in Internet Explorer. It also draws icons next to menu items.

CAlphaImageList: A replacement for CImageList that supports images with an alpha channel introduced in Windows XP. It automatically generates hot and disabled images looking like those in Internet Explorer 6.

CAlphaToolBar: An extension of CToolBar that allows using alpha channel images.

Under Windows XP, this interface automatically uses either the 3D style or the new flat style (compared in the picture above). Under older OS versions it uses the traditional 3D style. Another feature introduced in Windows XP is images with alpha channel. The icons can have smoothed edges so that they look good on every background, dark or bright. This interface works correctly with images from 16 colors to 32-bit alpha channel bitmaps under all versions of Windows.

2 Using It in Your Applications

Note: The menu bar only works in SDI frame windows. It can't be used in dialog windows or in MDI frame windows.

2.1 Toolbar images

The CAlphaImageList class supports two styles of images:

AILS_OLD: The image list uses a 16-color bitmap and doesn't create the hot and disabled images. The toolbar looks like in old style applications. The default background color (RGB 192,192,192) is used as transparent. You can change it by modifying the following line in AlphaImageList.cpp:

#define AIL_TRANSPARENT RGB(192,192,192)

To avoid some gray parts of buttons (like the disk label or the printer) being treated as transparent, I modified the original bitmap so that the magenta color is replaced by a slightly lighter gray (RGB 208,208,208), which is non-transparent. You can replace the Toolbar.bmp file with Toolbar4.bmp from the resources directory of the demo project. Before that, change the toolbar button size to 16x16 pixels.

AILD_NEW: The image list uses a 32-bit bitmap if comctl32.dll version 6 is detected or a 24-bit bitmap otherwise. You can use any number of colors in the toolbar bitmap. If the bitmap contains an alpha channel and the image list is 32-bit, the alpha channel is used as transparency information. Otherwise, the gray color (RGB 192,192,192) is transparent and all other colors are opaque.

You can create 32-bit bitmaps using Adobe Photoshop or a similar application. Even if the image has an alpha channel, you should use the gray color as the background so that the transparency is correct in previous OS versions—the only difference is that the icon edges won't be smooth in that case.

The resources directory of the demo project contains three versions of the new style toolbar bitmap: 8-bit, 24-bit, and 32-bit (with alpha channel). You can use whichever you want in your application. The bitmap was taken from the WTL sample application, with the background color changed to gray. The toolbar button size should be 16x16.

Note that Visual Studio will not let you edit the toolbar if the bitmap contains more than 256 colors. In that case, you will have to modify the resource file (YourApp.rc) by hand. The toolbar definition looks like this (16, 16 is the button size and IDR_MAINFRAME is the resource ID):

2.2 Menu resource

CMenuBar contains the following functions to load data from resources:

BOOL LoadMenuBar(UINT nID, int nStyle=AILS_OLD)

Load a menu resource. The nStyle parameter specifies the image list style (see above). You may call this function multiple times to replace the previous menu. The menu bar will automatically resize inside a rebar if needed. All images will be discarded.

BOOL LoadToolBar(UINT nID)

Load images from the bitmap resource and assign them to menu items with the same command IDs as in the toolbar resource. You may add multiple toolbars to a menu. You can create a separate toolbar resource that contains images for menu items, or use the default toolbar.

The menu bar assumes that the size of all images is 16x16 pixels. You can change this by editing the following lines in MenuBar.cpp:

#define MB_CX_ICON 16
#define MB_CY_ICON 16

2.3 Popup menus

CMenuBar also provides support for displaying context menus with the correct visual style and images. Put all popup menus in one resource and call the following function to load it:

BOOL LoadPopupMenu(UINT nID)

This menu will automatically use the same images as the window menu. There are two functions to display popup menus:

The first one uses the menu index; the second one uses the name of the menu, which may be more comfortable if your application uses many context menus. The ptPos is the menu position in screen coordinates.

Note: If you don't load a separate popup menu, the window menu will be used by default.

3 Final Notes

I found a bug in MFC 6 that caused the edit view to be incorrectly placed in the window, so that it covers a part of the rebar. The CEditView::CalcWindowRect should be replaced with CView::CalcWindowRect to fix this. Also, the edit view doesn't load and save the text correctly if comctl32.dll version 6 is used.

Implementing support for MDI applications is possible, but quite difficult. Anyway, the MDI architecture is not comfortable and out of date; check out my last article (Multithreaded SDI Applications) for a different solution. There are a lot of things that could be done, such as support for chevrons, popup buttons, and so forth. However, I tried to keep this code small, simple, and yet useful for most purposes.

very nice code and my suggestion for the "manifest" stuff

I tried your code and all I can say about your code is one word: wonderful.

There is one thing about the "manifest" stuff:
1) usually we have a "MyApp.manifest" file in the res subfolder, not the .xml file you used;
2) I would think that we could define IDR_MANIFEST in "Resource.h" as follows and do step 3):

popup menu

I used the features provided by you in my MFC application and it worked fine.

In my MFC application I have several popup menus. The items in these popup menus are not associated with the windows menu items. The IDs of the popup items are unique and are contained in their respective menu resource.

How can I use the techniques provided by you to these popup menus so that these popup menus have icons.

IE bars

Posted by AiType
on 09/23/2004 07:14am

Hi! I had the same problems by compiling the demo code. That's because you use an old user32.lib, and so an old . You have to donwload the new platform sdk from Microsoft to get the new libraries. See on: http://www.microsoft.com/msdownload/platformsdk/sdkupdate/downlevel.htm
bye

Top White Papers and Webcasts

When individual departments procure cloud service for their own use, they usually don't consider the hazardous organization-wide implications. Read this paper to learn best practices for setting up an internal, IT-based cloud brokerage function that service the entire organization. Find out how this approach enables you to retain top-down visibility and control of network security and manage the impact of cloud traffic on your WAN.

U.S. companies are desperately trying to recruit and hire skilled software engineers and developers, but there is simply not enough quality talent to go around. Tiempo Development is a nearshore software development company. Our headquarters are in AZ, but we are a pioneer and leader in outsourcing to Mexico, based on our three software development centers there. We have a proven process and we are experts at providing our customers with powerful solutions. We transform ideas into reality.