ShellBoost

Custom UI support

Custom UI can be used, for example, when an end-user selects a custom menu item. Because of ShellBoost out-of-process Architecture, as a .NET developer, you won’t be able to display custom UI elements (dialog boxes, windows, etc.) from in-process Explorer on end-user action.

However, ShellBoost comes with utility functions that will still allow you to display custom .NET UI elements (WPF windows, Winforms, etc.), from your custom application, in a modeless or modal way, with support for focus transition from explorer to your UI elements.

The Registry Folder sample demonstrates how to display .NET dialog box in response to menu item invocation:

Custom UI support - Picture 24

When the user clicks “Modify…” (or double clicks the item as the Bold font means “Modify…” is the default action), the following .NET WinForm is displayed, with keyboard focus set on the input TextBox that contains “This is a custom value”:

Custom UI support - Picture 25

Here is a commented extract of the Registry Folder sample:

// we override MergeContextMenu to add our custom “Modify...” menu item
protected override void MergeContextMenu(ShellFolder folder, IReadOnlyList<ShellItem> items, ShellMenu existingMenu, ShellMenu appendMenu)
{
    ...
    appendMenu.AddInvokeItemHandler(OnShellMenuItemInvoke);
    if (items.Count == 1 && !items[0].IsFolder)
    {
        var modifyItem = new ShellMenuItem(appendMenu, "Modify...");
        modifyItem.Tag = MenuCommand.Modify; // this is just an enum to remember what was clicked easily
        modifyItem.IsDefault = true; // this is why "Modify..." is displayed in bold font, and is the action that corresponds with end-user double-clicking the item
        appendMenu.Items.Add(modifyItem);
    }
    ...
}
 
private async void OnShellMenuItemInvoke(object sender, ShellMenuInvokeEventArgs e)
{
    // note e.MenuItem can be null for standard Shell commands
    var menu = (ShellMenu)sender;
    var mc = Conversions.ChangeType(e.MenuItem?.Tag, MenuCommand.Unknown); // get back the command enum value
    switch (mc)
    {
        ....
        case MenuCommand.Modify:
            if (e.Items.Count == 1) // we only support modification of one value at a time
            {
                // EditValue is a standard WinForm class
                using (var form = new EditValue())
                {
                    var valueItem = (RegistryValueItem)e.Items[0]; // we know the selected item is of RegistryValueItem (ShellItem)
                    form.LoadEditor(BaseParent.Hive, Path, valueItem.KeyName); // a custom EditValue method
                    
                    // show EditValue as a modeless form
                    // the same helper exists for a WPF Window instance
                    await WindowsUtilities.ShowModelessAsync(form, e.HwndOwner).ContinueWith((task) =>
                    {
                        if (task.Result == DialogResult.OK)
                        {
                            using (var key = OpenKey(true)) // open key is a helper method from the sample code, not shown here
                            {
                                // do the real work of changing the key value
                                key.SetValue(valueItem.KeyName, form.NewValue);
 
                                // ask the folder to refresh
                                e.Folder.RefreshShellViews();
                            }
                        }
                    });
                }
                return;
            }
            break;
        ....
    }
}

Hi-Dpi support

ShellBoost itself is agnostic with regards to Hi-Dpi support. The only UI it creates is the UI related to RPC connection problems between the host and the .NET server. This UI supports the “make text bigger” Windows display setting as well as the “make everything bigger” Windows display setting.

For example, here is this UI in 100% mode:

Hi-Dpi support - Picture 119

And the same UI in 225% mode:

Hi-Dpi support - Picture 123

For your custom UI, it depends on your code, settings, application manifests, and UI Framework you use (Winforms, WPF, etc.). Since your custom UI may be hosted visually near or over the Windows Explorer, it’s recommended to make sure your custom UI supports Hi-DPI.

Threading issues

If you need to show a window (like a WPF or Winforms window) from your namespace extension, you cannot use ShellBoost implicit threads (threads implicitly created by RPC incoming calls from the Shell) because these threads are not STA (Single Threaded Apartment) threads, which is a common requirement for UI-bound objects.

So, you can create your own STA threads or use ShellBoost utilities for that. For example, here is how you can show a WPF window before enumerating items:

public override IEnumerable<ShellItem> EnumItems(SHCONTF options)
{
    // run code on an STA thread
    var ret = ShellBoost.Core.Utilities.TaskUtilities.StartSTAThreadTask(() =>
    {
        var win = new MyWpfWindow(); // create the WPF window
        return win.ShowDialog(); // show it as a modal dialog
    }).Result; // => the result of ShowDialog
    ...
}  

Windows services

ShellBoost Custom UI is not supported if the ShellBoost folder server application is a Windows Services, because it’s not running in the same Windows Desktop as the client Windows Shell calling it.