Menus support

There are 3 types of menus that can be supported when developing a namespace extension:

Folder Context Menu: this menu is shown when the end-user right-clicks on a folder view, but not on a Shell Item. This is not to be confused with the menu shown when the user clicks on a Shell Folder.

Item Context Menu: this menu is show when the end-user right-clicks on a Shell Item (item or folder).

New Item menu: this menu is in fact a sub menu of the Folder Context Menu (its display text is “New”)  that is important because it allows end-users to create new items from the Shell, as opposed as creating new items from application (probably through the use of Common File Dialogs like Save).

Folder Context menu

Here is an example of such a menu in the Registry Folder Sample. Mouse was right-clicked anywhere in the folder’s view white area, but not on one of the 5 folders:

Folder Context menu - Picture 26

In this case, the menu is the standard Windows 10 shell menu. Here is another example where a “New” item with a sub menu was added by the namespace extension (since this is the Registry Folder sample, it’s meant to mimic “Regedit” behavior):

Folder Context menu - Picture 27

Here is the code that adds this sub menu:

// override ShellFolder’s class MergeContextMenu method.
// existingMenu contains the menu as it was already prepared by the shell.
protected override void MergeContextMenu(ShellFolder folder, IReadOnlyList<ShellItem> items, ShellMenu existingMenu, ShellMenu appendMenu)
{
    ...
    if (items.Count == 1 && !items[0].IsFolder)
    {
        // this is one shell item, do something else
    }
    else
    {
        // tags are placeholder for anything. we use them to remember what's the real command behind the menu item
        if (existingMenu.Items.FirstOrDefault(i => i.Text == "New") == null)
        {
            var newItem = new ShellMenuItem(appendMenu, "New");
            appendMenu.Items.Add(newItem);
 
            newItem.Items.Add(new ShellMenuItem(appendMenu, "Key") { Tag = MenuCommand.NewKey });
            newItem.Items.Add(new ShellMenuSeparatorItem());
            newItem.Items.Add(new ShellMenuItem(appendMenu, "String Value") { Tag = MenuCommand.NewValueString });
            newItem.Items.Add(new ShellMenuItem(appendMenu, "Binary Value") { Tag = MenuCommand.NewValueBinary });
            newItem.Items.Add(new ShellMenuItem(appendMenu, "DWORD (32-bit) Value") { Tag = MenuCommand.NewValueDWord });
            newItem.Items.Add(new ShellMenuItem(appendMenu, "QWORD (64-bit) Value") { Tag = MenuCommand.NewValueQWord });
            newItem.Items.Add(new ShellMenuItem(appendMenu, "Multi-String Value") { Tag = MenuCommand.NewValueMultiString });
            newItem.Items.Add(new ShellMenuItem(appendMenu, "Expandable String Value") { Tag = MenuCommand.NewValueExpandString });
        }
    }
    ...
}

Item Context menu

The list of items and sub items in a Shell Item (item or folder) context menu is the result of various combined operations from the Windows Shell and the 3rd parties installed on a PC (including the namespace extension that contains the item).

This is how you can add a “Modify…” menu item to a Shell Item (not a folder) in your namespace extension:

// override ShellFolder’s class MergeContextMenu method.
// existingMenu contains the menu as it was already prepared by the shell.
protected override void MergeContextMenu(ShellFolder folder, IReadOnlyList<ShellItem> items, ShellMenu existingMenu, ShellMenu appendMenu)
{
    ...
    // if there is only one shell item selected and it's not a folder
    if (items.Count == 1 && !items[0].IsFolder)
    {
        var modifyItem = new ShellMenuItem(appendMenu, "Modify...");
        modifyItem.Tag = MenuCommand.Modify;
        modifyItem.IsDefault = true;
        appendMenu.Items.Add(modifyItem);
    }
    ...
}

Item Context menu unwanted items

As a Shell Namespace Extension developer, you will not own everything that’s displayed in it, especially if the item is a physical Shell item. For example, if I have installed the renowned Notepad++ application and asked for Shell integration, Notepad++ setup will add the “Edit with Notepad++” menu item to any Shell item, including fully virtual ones (clicking on this item will do nothing as the Shell Item in this example does not support virtual content).

Item Context menu unwanted items - Picture 28

When overriding MergeContextMenu, ShellBoost will give you the existing menu as it’s been prepared when the Shell called ShellBoost to merge new items to it. From there you can remove existing items that you don’t want, adding the value of their Id property to the RemoveIds collection property of the ShellMenu class. However, in the example of Notepad++, it won’t work because, for some reason, the “Edit with Notepad++” menu item is added after the MergeContextMenu call.

New item menu

The “New item” menu is a sub menu of a Folder Context Menu that appears when right-clicking on the folder’s view, anywhere outside a shell item:

New item menu - Picture 29

This menu is entirely built by the Windows Shell, and depends on applications installed on the machine.

Namespace Extensions developed using ShellBoost can support this New Item menu. It’s automatic when the Shell Folder in the view is a physical Shell Item (it’s mapped to a real physical directory). You can however prevent this menu to appear if you set a ShellFolder instance’s AddNewMenuTemplatePath property to null.

For fully virtual Shell Folders, this menu will not appear. You can however manually add it to the Folder Context Menu with a code like this (demonstrated in the Web Folder Sample):

protected override void MergeContextMenu(ShellFolder folder, IReadOnlyList<ShellItem> items, ShellMenu existingMenu, ShellMenu appendMenu)
{
    // add an invoke handler
    appendMenu.AddInvokeItemHandler(OnShellMenuItemInvoke);
 
    // because we don't rely on file system, we won't have the "new" menu automatically set for us
    // so we must build one, from the standard one
    // fortunately, there is a helper for that
    appendMenu.MergeNewMenu();
 
    // once the new menu has been merged, remember what Id corresponds to what type of item and use that in the OnShellMenuItemInvoke method
}
 
private void OnShellMenuItemInvoke(object sender, ShellMenuInvokeEventArgs e)
{
    // TODO: get the clicked Id from the e argument and handle the item creation
}

As you see here, it’s shown the same way as for physical Shell Folders:

New item menu - Picture 15

Of course, since the folder is virtual, you will need to code whatever means creating a new item in this context.