- Introduction
- Developer’s Guide
- Samples
- Reference
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:
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”:
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:
And the same UI in 225% mode:
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.