Static context menus are limited because they are the same for every file object of a given type. Also, the number of files that can be processed through a static menu is limited by the program that is used to carry out the command. What if you need to process 20 files? What if you need different processing options based on the state of the file itself? There are also situations where you might need one context menu for a group of files and another for a single file. This is where dynamic context menus come into play.
A context menu handler is an ActiveX
DLL that implements two interfaces: IShellExtInit
and IContextMenu
. A third interface,
IDataObject
, is required to implement
IShellExtInit
. It is not implemented by the object
itself but exists as a method parameter in
IShellExtInit
. We’ll explore these
interfaces in greater depth after we examine how the shell uses a
context menu handler to assemble a context
menu.
The process begins when one or more files is right-clicked in
Explorer. When this occurs, the shell checks the
shellex
key under the application identifier key
to see if a context menu handler has been defined for the selected
file type. In the case of the .rad
file, the
shell would look under the following key:
HKEY_CLASSES_ROOT/ radfile/ shellex/ ContextMenuHandlers/
If you select 15 files that are of all different types, there is still only one file with active focus: the last file selected in the group. It is this file for which the shell attempts to find an associated context menu handler.
If a context menu handler exists, the
shell loads the handler and calls
IShellExtInit::Initialize
. One of the parameters
of Initialize
is a reference to
IDataObject
. The shell uses
IDataObject
to tell us how many files are selected
and what their names happen to be. This gives us the opportunity (as
the implementors of IShellExtInit
) to save the
filenames and the number of selected files for later use. This
information can be stored in private member variables within the
class. Later, when a command is actually selected from the context
menu, the array of files can be referenced and processing decisions
can be made.
Next, the shell calls
IContextMenu::QueryContextMenu
. This method is
responsible for adding items to the context menu. The shell passes
into the method a handle to the context menu, called an
HMENU
. An index representing a valid insertion
point for the menu item is also passed in. Adding the menu item is
simply a matter of calling the InsertMenu
API
.
You might want different menu
items displayed based on whether one or multiple files have been
selected. Since the number of files selected can be determined in
IShellExtInit::Initialize
, this becomes a trivial
matter. You also have the ability to base the menu item on the file
itself. In addition to the number of files selected, you would also
already know the filenames in question. This means you could open the
file, retrieve information, and base the menu item on actual data. Or
you could examine some other attribute of the file (such as its
creation date, its size, or its read-only status) and base the menu
item on that information as well.
At this point, the shell displays the context menu with the
additional menu items. Once the context menu is displayed, the shell
attempts to call IContextMenu::GetCommandString
whenever the mouse is moved over the new context menu item. This
allows you to provide a help string that will be displayed in the
status bar of Explorer when the context menu item is
highlighted.
When the command is actually
selected, the shell calls
IContextMenu::InvokeCommand
on the handler. The
method allows you to determine which context menu item has been
selected, and as a result your handler can carry out the appropriate
actions.
Get VB Shell Programming now with the O’Reilly learning platform.
O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.