Common Dialogs

Common Dialogs (Open, Save As, etc.) support is automatic when using CBFS Shell. The CBFS Shell native proxy DLL will be loaded into any process address space as soon as this process calls a specific Shell function. This behavior is not limited to Common Dialogs; the use of other Shell functions can cause the native proxy DLL to load into the corresponding host process.

Example 1: In this example, Notepad opens a file in a "CBFS Shell" Namespace Extension, just like it were a regular folder:


Example 2: In this example, Microsoft Word 2016 opens a file in the same extension (but this time, the extension is in the Details view mode and has an extra custom icon for demonstration purposes):


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 items that are filesystem 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 in a specific application, you will have to test whether or not this scenario requires filesystem Shell items.

Technically, Common Dialogs are exposed through the Windows IFileDialog interface. If you are developing an application and only need filesystem Shell items, you would use the IFileDialog::SetOptions method with the FOS_FORCEFILESYSTEM flag. If you want to support both physical and virtual Shell items, 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)

Independent from CBFS Shell, although both scenarios generally will 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 items. For example, an application such as Windows Notepad does support virtual items for read-only/open operations. The same is true for two other well-known applications: Notepad2 and Notepad++.

Save scenarios with virtual items, however, are much more complicated to support and may even be impossible for some applications. These applications don't know how to handle non-physical items returned by the Common Dialog.

If you want to maximize overall Shell compatibility (as well as other apps), especially for Save scenarios, it's better to use physical items for items that you want to use from Common Dialogs (note that in a given folder, you may mix physical and virtual Shell items). Your code also may check the client host process using the ShellContext class and may change its Shell item's behavior (physical vs. virtual) if the client process is not Explorer (e.g., use the code below):

public class MyFolder : ShellFolder
{
    public MyFolder(ShellFolder parent, ShellItemId id)
        : base(parent, id)
    {
        ...
        if (ShellContext.Current.IsClientProcessWindowsExplorer == false) // we're using a CBFS Shell-provided utility
        {
            // our client process is not 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 information).

Common Dialog Context

Classes that derive from Shell Folder instances can react to some Common Dialog events if they override the ShellFolder's OnFileDialogEvent method, as demonstrated by the following code:

// This will get called only in a Common Dialog box 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 filesystem path)
            var path = e.CurrentSelectionIdList.GetPath();
            // TODO: do something with this...
        }
    }
}

Custom Dialog Context

Classes that derive from Shell Folder instances also can react to some custom Dialog Box events, provided that 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.). 
        // CBFS Shell 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 filesystem path)
        var path = e.CurrentSelectionIdList.GetPath();
        // TODO: do something with this...
    }
}

Copyright (c) 2022 Callback Technologies, Inc. - All rights reserved.
CBFS Shell 2022 .NET Edition - Version 22.0 [Build 8172]