HOWTO: Support Common Dialog Browsing in a Shell Namespace Extension
ID: Q216954
|
The information in this article applies to:
-
Microsoft Win32 Software Development Kit (SDK), on platform(s):
-
Microsoft Windows versions 95, 98
-
Microsoft Windows NT 4.0
-
Microsoft Windows 2000
SUMMARY
When implementing a shell namespace extension, it is a common misconception that the extension can be easily browsed using the File Open and Save File As dialog boxes. It is possible to implement a shell namespace extension that can be browsed using these common dialog boxes; however, there are certain requirements that must be fulfilled to make this possible. This article describes what is necessary to implement a shell namespace extension that can be browsed using the common dialogs and the reasons that these steps are necessary.
MORE INFORMATION
To support browsing in your shell namespace extension, all of the following restrictions must be met:
- At a minimum, the namespace extension's objects must have the following attributes:
- The extension's root folder and sub-folders must have both the SFGAO_FILESYSANCESTOR attribute and the SFGAO_FILESYSTEM attribute.
- The extension's nonfolder items must have the SFGAO_FILESYSTEM attribute and not the SFGAO_FILESYSANCESTOR attribute.
- The extension must be able to supply a valid file system path in response to its IShellFolder::GetDisplayNameOf when SFGAO_FORPARSING is specified. For example, assume your extension is rooted off of the Desktop, has the name MyView, and an item with the name MyItem exists under the root of the namespace. When the user attempts to open MyItem, the file common dialogs will obtain the name of the containing folder by calling IShellFolder::GetDisplayNameOf with SHGDN_FORPARSING. In response to this, your namespace extension must supply a valid file system path. If your namespace's local storage is under C:\MyView, then IShellFolder::GetDisplayNameOf must supply the name C:\MyView. The name(s) of the selected item(s) will then be concatenated onto the end of this path. A description of how the common dialogs obtain the item names follows.
NOTE: Your extension's IShellFolder::GetDisplayNameOf must also be able to provide a valid file system path for any item that it contains. This is especially important because future versions of the common dialogs may use this method to obtain the full path to the item name.
- When the extension is registered, the following registry entries must be added:
- Under HKEY_CLASSES_ROOT - CLSID - {<clsid>} - InprocServer32, create a string value with the name of LoadWithoutCOM, leaving the data as an empty string. This allows the shell to load the extension even if COM has not been initialized.
- Under HKEY_CLASSES_ROOT - CLSID - {<clsid>} - ShellFolder, create a string value with the name WantsFORPARSING, leaving the data as an empty string. This causes the shell to call the extension's IShellFolder::GetDisplayNameOf for the root folder if only the SFGAO_FORPARSING is specified. Without this value, the shell just provides the registered name for the root folder. In some cases, the File dialog box attempts to verify that the name returned by GetDisplayNameOf is a valid path. Because of this, it is necessary to have the extension provide the root folder's name rather than having it come from the registry.
- Your namespace extension must also be able to map its root and every folder and item under it to an object that actually exists within the file system. The reason for this is that the common dialog builds the returned name from the path of the folder combined with the name(s) of the selected item(s) (as described above). At no point will the common dialog attempt to obtain the entire name from the extension. Because of this, the extension never has an opportunity to re-map the selected name to the name and location of the "real" file object.
- The shell view must call the ICommDlgBrowser methods in response to the proper events. The common dialog's ICommDlgBrowser interface pointer is obtained by calling IShellBrowser::QueryInterface.
Because the common dialog is only hosting the view and not implementing the view, it is necessary for the view to notify the host when certain events occur. If the view does not notify the host, the host will not be able to perform subsequent actions that are necessary for proper operation. The following bullets list the events that the host must be notified of and how to perform this notification.
- When enumerating the items to be added to the view, the view must call ICommDlgBrowser::IncludeObject for each item to be added. If IncludeObject returns S_OK, then the common dialog has approved the item and it can be added to the view. This method allows the common dialog to filter certain file types. For example, if the common dialog only wants to view objects that have the .txt file extension, IncludeObject will only approve items with the .txt file extension.
- When the default action is executed on an item in the view, such as when the user double-clicks the item, the view must call ICommDlgBrowser::OnDefaultCommand. If OnDefaultCommand does not return S_OK, the view executes its default command for the item. This allows the common dialog to override the default command. For example, if the user double-clicks a folder object in the view, OnDefaultCommand will not return S_OK, which, in most cases, will cause the view to navigate to the folder. If, however, the user double-clicks an item in the view, the common dialogs interpret this as a command to select the item and close the dialog. In this case, OnDefaultCommand will return S_OK to prevent the view from trying to open the item itself.
- Whenever the view gains the focus, loses the focus, or an item is renamed or when the selection in the view changes, the view must call ICommDlgBrowser::OnStateChange with the appropriate event flag. This allows the common dialog to take appropriate action in response to the event. The most important of these events is when the selection in the view changes. When the selection in the view changes, the view calls ICommDlgBrowser::OnStateChange with CDBOSC_SELCHANGE. In response to this event, the common dialog will call the extension's IShellView::GetItemObject with IID_IDataObject and SVGIO_SELECTION. The extension must supply an IDataObject that presents the selected items in response to this. Once the IDataObject interface has been obtained, the common dialog will call IDataObject::GetData with CFSTR_SHELLIDLIST to get the ITEMIDLIST(s) for the selected item(s). The data object must supply a correctly filled out CIDA structure in response to this. The common dialog will then use the ITEMIDLIST(s) in a call to IShellFolder::GetDisplayNameOf to get the display name for each item. This is how the common dialog obtains the name(s) for the selected items that it puts in the dialog's edit control.
If you conform to all of the restrictions detailed above, users can browse into your namespace extension using the common dialogs.
In addition, the redirection detailed in step 2 is possible only in Shell32.dll version 4.71 or greater. For Shell32.dll versions less than 4.71, this kind of redirection is not possible. However, on both versions you can have a folder created on the desktop and the view for this folder can be provided by the namespace extension using the Desktop.ini method.
Additional query words:
Keywords : kbCmnDlg kbCmnDlgFileO kbCmnDlgSave kbExtension kbNameSpace kbNTOS400 kbWinOS2000 kbSDKPlatform kbWinOS95 kbWinOS98 kbGrpShell
Version : WINDOWS:95,98
Platform : WINDOWS
Issue type : kbhowto
Last Reviewed: May 14, 1999