The Windows shell provides the ability to extend the context menu with new menu options. To enable this feature a shell extension must register an
IContextMenu interface for a specific file extension or the global ‘*’ extension. The Mini Shell framework discussed in this article provides a set of helper classes that can be used to create such a shell extension. The
IContextMenuImpl class provides the following functionality:
- An embedded class
CMenu that makes it easy to create the correct menu entries.
- A registration system that will forward owner drawn menu events to a ‘paint’ handler and select a menu item command to the correct command handler.
CSmallBitmapHandler class is provided by the framework to create menu items with a small bitmap in front of the menu text.
My original plan was to document
IShellFolderImpl in one article. During finalization of the
IShellFolderImpl, I decided to split the description of both classes in two articles. The primary reason for this decision is that,
IShellFolderImpl is very complex and requires on its own already a lot of text to describe (will be documented in part 3). For more background info about the design model and the used .vvv file sample the reader is referred to the first article on the Mini Shell extension Framework.
The requirements for the framework are not changed since the first article. VC.NET 2002 + latest SDK or VC.NET 2003. The framework is verified on Win 98, ME, W2K and XP.
A context menu extension is, as all other shell extensions, a COM object. The first requirement is thus, the registration of the COM class. The framework includes two ATL registrations script to do this. One registration script is intended to be used for files that are normally opened with an application and the other script should be used if the file is opened in explorer (in combination with a shellfolder extension). The included VVV sample demonstrates also a shellfolder extension and uses therefore the contextmenu_sf.rgs registration script.
class ATL_NO_VTABLE CContextMenu :
public CComCoClass<CContextMenu, & __uuidof(CContextMenu)>,
static HRESULT WINAPI UpdateRegistry(BOOL bRegister) throw()
bRegister, L"Sample ShellExtension ContextMenu",
The code example above shows the class definition and the static function
UpdateRegistry that ATL will call to register and unregister the extensions. This static function is normally implemented with the
DECLARE_REGISTRY_RESOURCEID macro which is added automatically by the ATL class wizard. To instruct ATL which interfaces our object supports a ‘COM_MAP’ must be setup. The code below shows the interfaces the VVV sample selects to support. The
IContextMenu3 interfaces are needed because the VVV sample uses an owner drawn menu item.
The base class of the framework
IContextMenuImpl<> must be notified which extensions needs to be handled.
The last required function that must be implemented is the
OnQueryContextMenu. This function is called by the framework after it received a call from the shell through the COM function
QueryContextMenu. The code below shows the implementation for the VVV sample. The first step checks if the files selected by the user only contain .vvv selected files. In the second step the extension checks if only one file is selected (theoretically, only one check is needed). The first entry that is created is a submenu with an owner draw handler. Two menu items are added to this new submenu. The
CSmallBitmapHandler class is provided by the framework.
CAboutMSFCommand are command handlers of the VVV sample.
void OnQueryContextMenu(IContextMenuImpl<CContextMenu>::CMenu& menu,
const std::vector<CString>& filenames)
if (filenames.size() != 1)
CMenu menuVVV =
The framework uses functors to forwarded the selected menu item as action to the shell extension. These functor objects must be passed as one of the arguments when menu items are created. The functor
CEditWithNotepadCommand used by the sample will start notepad to edit the selected .VVV file. The
CreateProcess function that is used is a ‘short’ version of the Win32
CreateProcess function and is one of the utility functions provided by the framework.
class CEditWithNotepadCommand : public CContextCommand
virtual void operator()(const CMINVOKECOMMANDINFO* ,
const std::vector<CString> & filenames)
ATLASSERT(filenames.size() == 1);
CString strCmd = _T("notepad.exe \"") + filenames + _T("\"");
CAboutMSFCommand functor is even simpler. It just formats a string and displays it to the user. The
IsolationAwareMessageBox messagebox function is called to use the new XP style (when running on XP). Tip:
MessageBox is one of the functions that is not redefined by the SDK headers when isolation aware is enabled, it must be called explicit.
class CAboutMSFCommand : public CContextCommand
virtual void operator()
(const CMINVOKECOMMANDINFO* pici,
const std::vector<CString> & )
The basic menu system has changed very little in the history of Windows. To provide a ‘cooler’ look, many applications draw their own menus. The windows shell menu itself only uses images for the ‘open with’ and ‘send to’ submenus. A contextmenu extension can also use owner draw menu items. There are three options to add graphics to a menu item:
- Owner draw. The extension is completely free to draw the menu itself.
- Using a small menu bitmap. Menu items can use a small bitmap before the text. The X mark before ‘close’ in the system menu is a good example (not supported on all Windows versions).
- Use a custom check mark.
The framework provided a support class
CSmallBitmapHandler that can be used to add small bitmaps (13x13) to menu items. This class uses the custom check mark option to add the small bitmap before the text. The main advantage of this technique is that the text of the menu item is drawn the same as all other menu items. This prevents that the ‘added’ menu item looks different or strange. Complete owner drawn items and bitmap menu items are better reserved for a submenu that is under complete control of the extension.