Welcome to shell: revealed Sign in | Join | Help
in Search

Shell Blog

Shell Namespace Extension: Adding Custom Command Module Items

Overview

In my earlier post, I showed how to create a Shell Namespace Extension using the default IShellView implementation (also known as DefView).  One thing you might have noticed from the sample is that the Commands Module is void of even the default items such as “Organize” and “Views”. 

Commands Module - FolderViewImpl

If you are developing your own Namespace and want to include the default buttons and/or add your own elements to the Commands Module as well, how do you accomplish this?  The answer:   you must implement the IExplorerCommand, IExplorerCommandProvider and IEnumExplorerCommand interfaces.

Below I describe what each of the interfaces is used for and what you need to do to properly implement them in your code.

IExplorerCommandProvider

After your Namespace is loaded, the Shell will ask your Namespace for an instance of an IExplorerCommandProvider (via your CreateViewObject implementation).  This interface exposes two methods:  GetCommand and GetCommands.  The Shell calls the GetCommand method to retrieve a specific IExplorerCommand object that matches the supplied GUID (Each command is identified by a GUID).  The GetCommands method is called to retrieve an IEnumExplorerCommand instance.  This object enumerates all the IExplorerCommand instances for the namespace.

You Namespace is queried for its implementation of IExplorerCommandProvider via its IShellFolder's implementation of CreateViewObject.  The REFIID passed to CreateViewObject will be IID_IExplorerCommandProvider.  The Shell will then use this interface to retrieve your Commands Module items – which are implementations of the IExplorerCommand interface.

IExplorerCommand

The IExplorerCommand interface is used to provide the appearance and behavior of the item to Explorer’s Commands Module.  Most of the methods pass an IShellItemArray which identifies what items are currently selected in the view.  This information can be used by the implementation to customize the behavior for different selections or if no items are selected.  For example, if no items are selected, you may wish to set the state to ECS_DISABLED or ECS_HIDDEN to grey-out or remove the item completely from the Commands Module, respectively.

The methods exposed by this interface are described below.

Method

Description

EnumSubCommands

Returns an IEnumExplorerCommand instance used to enumerate sub commands of the current command.  The Shell will only call this method if the GetFlags method returns ECF_HASSUBCOMMANDS .  It is important to note here that while it is possible to do so, sub commands that have sub commands themselves are not encouraged. 

GetCanonicalName

Retrieves the globally unique identifier (GUID) associated with this command

GetFlags

Retrieves the flags associated with this command.  These flags specify the appearance and behavior of the command on the Command Module.

GetIcon

Retrieves an icon resource string.  This string is in the form of “myfile.dll,id”.  For example: “shell32.dll,-101”

GetState

Retrieves the state of the command item.  This is the first method of the interface that is called.  The state that is returned affects the appearance and behavior of the command item.  This method also passes a BOOL to let the command implementation know if the slow response rule is in effect.

GetTitle

Retrieves the string to display for the command item.

GetToolTip

Retrieves the string to use in the ToolTip associated with this command item.

Invoke

Called by the Shell when the user has activated a command on the Commands Module.

The above methods GetState and GetFlags return values that determine the appearance and behavior of the item in the Command Module.  In the table below are screenshots of the command resulting from the combinations of the flags/states values.

 

ECS_ENABLED

ECS_DISABLED

ECS_HIDDEN

NONE

ECF_HASSUBCOMMANDS

ECF_HASSPLITBUTTON

ECF_HIDELABEL

ECF_ISSEPARATOR

N/A

ECF_HASLUASHIELD

 

ECS_CHECKBOX

ECS_CHECKBOX|

ECS_CHECKED

NONE

ECF_HASSUBCOMMANDS

ECF_HASSPLITBUTTON

ECF_HIDELABEL

ECF_ISSEPARATOR

N/A

N/A

ECF_HASLUASHIELD

*ECS_CHECKBOX and ECS_CHECKED only apply to sub items

** ECF_ISSEPARATOR can only be added as a sub item

Slow Response Rule

The second parameter of the GetState method is a BOOL (fOkToBeSlow) that lets the implementation of IExplorerCommand know if the “slow response rule” is in effect.  If this value is FALSE, and your implementation performs slow operations (such as I/O, network calls or calls to out of thread COM objects) then your command should return E_PENDING.  This will cause the Commands Module to call the command’s GetState (and other methods) on a background thread with fOkToBeSlow set to TRUE.  This prevents slow operations in your implementation from running on the UI thread, thus preventing performance issues.

Command Item Ordering

It is important to note here that the developer of the Namespace Extension has no control over the ordering of command items.  For example, you cannot force your command items before the default View and Organize command items or have the View or Organize command items renamed/removed.  Items are simply appended to the end of the Commands Module in the order returned from the IEnumExplorerCommand instance.

IEnumExplorerCommand

The IEnumExplorerCommand is returned to the Shell by the GetCommands method of the IExplorerCommandProvider interface.  As the name suggests, it permits enumeration of the IExplorerCommand instances by the Shell.

FolderViewImpl Sample Code

The above interfaces have been implemented in the attached Shell Namespace Extension sample code derived from the FolderViewImpl SDK sample.  The structure of the command items (as well as sub items) is data-driven from an array of structures that define the command items (see the array of FVCOMMANDITEMs in fvcommands.cpp).   This approach was used to make it easy to experiment with the hierarchy of command items as well as their behavior/appearance.   The way you implement commands in your Namespace Extension may differ.

Commands Module - Modified FolderViewImpl

The above is a screenshot of the modified SDK sample.  Notice we now have the default command items (Organize and Views) as well as our custom items.  The Display command item performs the same function as right-clicking items in the view and selecting “Display” from the context menu.  The Settings button is used to demonstrate a command item with sub items.  All it does is display a message box with the name of the sub item when the user invokes the specified sub item.

It should also be noted that if you are using a custom view in your Namespace by implementing your own IShellView (instead of using DefView) you will need to include an implementation of IFolderView::GetFolder.  In your GetFolder implementation you will need to include the ability to QueryService for SID_SFolderView.

Building the FolderView SDK Sample

  1. To build the FolderViewImpl sample, be sure to download and install the Windows SDK
  2. Download the modified FolderView SDK sample
  3. Launch FolderViewImpl.sln in Visual Studio
  4. Open the properties for the project
  5. Add a path to the SDK includes to the C/C++ - General page
  6. Add a path to the SDK libs to the Linker – General page
  7. Build

Installing the FolderView SDK Sample

  1. Once you have built the sample, copy the FolderViewImpl.dll and FolderViewImpl.propdesc to the same directory
  2. From an elevated cmd window, regsvr32 FolderViewImpl.dll
  3. Restart explorer
  4. Open explorer to Computer
  5. There should be a list item named “FolderView SDK Sample”
Published Wednesday, September 05, 2007 1:43 AM by chrdavis

Comments

 

Jim said:

Hey guys, thanks for this, I had no idea this was available.

A suggestion on a future post, or possibly just answer it here - is there a way to add buttons to the "Show only" toolbar in the Search panel for other specific media types? "Other" is too general, and fills with tons of junk, making it rather worthless. I was looking for a way to customize this using a custom search, but couldn't find a way to associate a new button with one.

September 6, 2007 3:31 PM
 

chrdavis said:

Jim - unfortunately the search panel you mention is not customizable.

September 20, 2007 4:09 AM
 

ParTim said:

Good article, thanks for that!

Can the author or someone else to tell me how can a Shell namespace extension using an own view object (not DefView) react to user input in Explorer's Search box that is located at top right corner of the browser window? This Search box is available in Windows Vista only. For example, when the user types ".txt" in the Search box, our view should show text files only. The Shell should give us a way to support what the user expects so that we could achieve normal interoperability between Explorer and custom shell namespace extensions.

September 20, 2007 1:54 PM
 

chrdavis said:

ParTim - in Vista there is no way to modify your custom view to support search as you describe.  Using the search functionality in your namespace is only possible if you use DefView.  We are working to change this in the next version of Windows to allow search to work for custom views.

September 20, 2007 4:04 PM
 

ParTim said:

What does it require from a Shell namespace extension using a custom view to make the command bar reacting to selection changes in the view? When a selection changes, items on the command bar should often change their appearance based on the current selection. An article and detailed code sample about a Shell namespace extension using a custom view including a FULL integration with the command bar would be very helpful.

September 21, 2007 3:39 AM
 

chrdavis said:

ParTim - This does not appear to be possible via your custom view implementation.  Moving forward, in order to take full advantage of the new features in explorer, you will have to use DefView.  Your existing namespace will continue to work, but you are not guaranteed to be able to take advantage of the next great feature in explorer in future releases.

October 2, 2007 12:58 AM
 

Jim Barry said:

Thanks for writing this article. But why does this information not appear in the SDK documentation? The documentation for IShellBrowser::SetToolbarItems doesn't even mention that it doesn't work in Vista.

And I'm pretty distressed to learn that there is no way for a custom view implementation to integrate properly with the command bar or search box. What were you guys thinking?

October 19, 2007 10:53 AM
 

chrdavis said:

Jim - good to hear from you again!  I have notified the MSDN content owners about your documentation issues.  We will also add an entry on MSDN communicating the reasoning surrounding our decision to only support new features using the default view in explorer.  I will add a link to this content here when it becomes available.

October 23, 2007 2:35 PM
 

Jim Barry said:

Christopher - thanks for the reply. The problem is that this isn't a purely new feature. You took away the old mechanism (i.e. the ability to add toolbar buttons via IShellBrowser::SetToolbarItems) and replaced it with something that doesn't work properly with custom view implementations. Do you see why some folks might not find this acceptable?

November 12, 2007 7:02 AM
 

purefusion said:

So how can we create that damned "New Folder" button that's missing in explorer, but is there is save-as diologs inside programs? That's probably the most annoying missing item in Windows Vista's Explorer.

I hope Microsoft fixes this flaw in Vista Service Pack 1, it's on my wish list. Until then, is there anything we can do?

January 14, 2008 8:47 PM
 

binouye said:

If we use the DefView, does anything special need to be done to enable search functionality.  In particular, does "Did you find what you were searching for?" appear and will clicking "Search in File Contents" index the files?

January 21, 2008 3:56 PM
 

cpqtech said:

Just created a namespace extension rooted in My Computer, built using C# (I know this is not recommended) .Net 2.0 Runtime everything works fine except in the commondialog box I can't browse subfolders. I see the items on the root, however.

I implemented a custom DataObject that returns a CIDA structure through a call to GetData.

After this call the view requests GetAttributes and GetDisplayNameOf on my subfolder but never calls BindToObject? I suspected my CIDA might have been incorrectly allocated but I don't htink this is the issue since the  GetAttributes and GetDisplayNameOf are being called with the correct pidl.

The namespace is registerd for WantsForParsing but does not represent physical filesystem objects, so I return the Temp path in response to request to GetDisplayname with the

ForParsing flag.

Any ideas what I may be doing wrong.

February 5, 2008 1:24 PM
 

chrdavis said:

cpqtech - You need to make sure your folder has (SFGAO_FOLDER | SFGAO_STORAGEANCESTOR) or (SFGAO_FOLDER | SFGAO_FILESYSANCESTOR).

Sounds like the former is the correct thing, since you said you don’t represent file system objects.

Then, you need to support SFGAO_STREAM on the individual items within your namespace, and reply to BindToObject for IStream on them.

Then the open file dialog takes care of reading from the stream and creating a temp file for applications to open.

This only works with the open dialog, not the save dialog (unless an application is using the Vista-only COM API, and accepts arbitrary IShellItems).

February 7, 2008 1:07 AM
 

chrdavis said:

binouye - In response to your question on how to get search to work in this namespace sample, you need to do the following. Not that this will only work if you are using Defview as your shell view.

First, have your folder view callback (IShellFolderViewCB) object implement IFolderViewSettings

Next, implement IFolderViewSettings::GetFolderFlags() and return FWF_USESEARCHFOLDER

       IFACEMETHODIMP GetFolderFlags(__out FOLDERFLAGS *pfolderMask, __out FOLDERFLAGS *pfolderFlags)

       {

           // do a deep search when word wheeling

           *pfolderMask = FWF_USESEARCHFOLDER;

           *pfolderFlags = FWF_USESEARCHFOLDER;

           return S_OK;

       }

February 8, 2008 5:05 PM
 

sunshine_msdn said:

hi, i found tha the first column can not be sorted by click column header or click menu.but the second can. why ? and my NSE with DefView also has this problem no vista. how can i correct it?

thanks!

March 5, 2008 3:33 AM
 

chrdavis said:

sunshine_msdn - you are correct.  There was a one-line bug in the LoadFolderViewImplDisplayStrings method in utils.cpp.  The HRESULT should be initialized to S_OK.  I have made the fix and will update the source available in my most recent blog post.  

March 10, 2008 6:07 PM
 

sunshine_msdn said:

I have solved this problem by import VC6 project to VC2005 project.

thanks chrdavis.

March 13, 2008 9:31 PM
 

idas said:

----

please,

is it possible [for example]  the  'organize'  [command? ]  to be exist as a shortcut, so the menu of organize to be open when we select with the mouse this kind of shortcut?  

thanks in advance.

May 3, 2008 4:41 AM
Anonymous comments are disabled
Powered by Community Server, by Telligent Systems © 2006 Microsoft Corporation. All rights reserved. Terms of Use | Trademarks | Privacy Statement.