ShellBoost

Common Dialogs support

Common Dialogs (Open, Save As, etc.) support is automatic when using ShellBoost. The ShellBoost native proxy assembly will be loaded in-process implicitly by the hosting application process as soon as it calls some Shell functions. In fact, this is not limited to Common Dialogs, other Shell functions can end up loading your namespace extension native proxy assembly in their process.

Here is the example of Notepad opening a file in a “ShellBoost” namespace extension, just like it was a regular folder:

Common Dialogs support - Picture 11

And here is the example of Microsoft Word® 2016 opening a file in the same extension (note this time the extension is in details view mode and has an extra custom icon - for demonstration purposes):

Common Dialogs support - Picture 12

However, any application that uses a Common Dialog can customize the way it works. For example, many applications require that the File Open dialog only displays Shell Item that are file system items. These applications will not see fully virtual Shell Items. As a Shell Namespace Extension developer, there is not much you can do about this, if you need to support Common Dialogs for some specific applications, you will have to test if it requires a file system shell item or not.

Technically, Common Dialogs are exposed through Windows’ IFileDialog interface. If you are developing an application and only need file system shell items, you would use the IFileDialog::SetOptions method with the FOS_FORCEFILESYSTEM flag. If you want to support both physical and virtual shell item, then this flag should not be specified.

Open vs Save Scenarios

There are basically two major Common Dialog scenarios:

Open scenarios (Open File…)

Save scenarios (File Save As…)

Independently from ShellBoost, while both scenarios will, in general, work well with Shell Namespace Extensions that offer physical Shell Items (items with the FileSystemPath property set), the story is quite different when the Shell Namespace Extension offers virtual items (items without the FileSystemPath property set).

Open scenarios will work with many applications, even with virtual. For example, an application such as Windows Notepad does support virtual items for read-only/open operations. It’s the same with two other well-known applications such as Notepad2 and Notepad++ for example.

However, “Save” scenarios with virtual items are much more complicated to support, or even impossible for some applications, because these applications don’t know how to handle non-physical items returned by the Common Dialog, usually because they use legacy Windows APIs.

So, if you want to maximize overall Shell (and other apps) support, and especially for “Save” scenarios, it’s better to use physical items, for items you want to use from the Common Dialogs (note in a given folder, you can mix physical and virtual Shell items). Your code can also check what’s the client host process, using the ShellContext class, and change its Shell Items behavior (physical vs virtual) if the client process is not Windows Explorer. For example, with a code like this:

public class MyFolder : ShellFolder
{
    public MyFolder(ShellFolder parent, ShellItemId id)
        : base(parent, id)
    {
        ...
        if (ShellContext.Current.IsClientProcessWindowsExplorer == false) // we’re using a ShellBoost provided utility
        {
            // out client process is not Windows Explorer, act accordingly ...
        }
        ...
    }

Another solution is to use Related Items that allow you to associate physical items to virtual items (see the Related Items chapter for more on this).

Common Dialog context

Starting with ShellBoost version 1.2.6.0, classes deriving from Shell Folder instances can react to some Common Dialog events if they override the ShellFolder’s OnFileDialogEvent method, as demonstrated in the following code:

// This will only get called in a Common Dialog hosting scenario 
protected override void OnFileDialogEvent(object sender, FileDialogEventArgs e)
{
    // Called just before the dialog is about to return with a result
    if (e.Type == FileDialogEventType.FileOk)
    {
        if (!e.IsFileSave && e.CurrentSelectionIdList != null)
        {
            // we're in file open, not in file save, we can get the selected item PIDL
            // and/or we can get its path (not necessarily a file system path)
            var path = e.CurrentSelectionIdList.GetPath();
            // TODO: do something with this...
        }
    }
}

Custom Dialog context

Starting with ShellBoost version 1.8.1.1, classes deriving from Shell Folder instances can also react to some custom Dialog Box events, provided they host a standard Shell View, with the same type of code:

// This can now be called in a custom dialog box hosting scenario 
protected override void OnFileDialogEvent(object sender, FileDialogEventArgs e)
{
    // OK/Open/etc. button was pressed. OK is the button with id 1. Cancel is the button with id 2.
    if (e.Type == FileDialogEventType.OnButtonOk)
    {
        // since this is a custom dialog box, we don’t know if we are in a file open or something else.
        // however, we can use the window handle to determine more information (for example the title, or buttons names, etc.). 
        // ShellBoost provides a useful wrapper class for this:
        var win = new Win32Window(e.Hwnd);
        // TODO: do something with this...
 
        // and we still can get the path (again not necessarily a file system path)
        var path = e.CurrentSelectionIdList.GetPath();
        // TODO: do something with this...
    }
}