Click here to Skip to main content
15,880,972 members
Articles / Programming Languages / C++
Article

Namespace Extensions: The Tasks Band Disclosed

Rate me:
Please Sign up or sign in to vote.
4.86/5 (25 votes)
28 May 20036 min read 71.4K   28   8
This article explains how to manipulate the folder tasks shown in your namespace extension, using undocumented COM interfaces.

Introduction

In Windows XP, Explorer has a cool new feature: A pane on the left that contains items like "other places", "Folder Tasks" and "Picture Tasks". But what if you are developing your own namespace extension? Can you put anything you like there? Microsoft will tell you, you can't change anything in it. But fortunately, we figured out a way to do this.

The information disclosed in this article was discovered while developing Whirling Dervishes NSELib, the first commercial product to implement this feature. It can be found here.

The function SHCreateShellFolderView(Ex)

The recommended way to implement your namespace extension is creating a def view object. You do this by calling SHCreateShellFolderView(Ex). This is described in detail in the article Namespace extensions: The undocumented Windows Shell.

The article dates from 1999 and is therefore slightly out of date, but the basic workings are still the same in Windows XP. This article assumes you are using these functions to create the view object for your namespace extension. It relies on new callback messages that were introduced in Windows XP.

At this point, it is very well possible that you don't know what I'm talking about. In this case, you will have to read a few other articles on this web site that get you started, and try to implement your first namespace extension. After that you can come back here.

Vocabulary

First let's give everything a name so that we know what we are talking about.

  • Tasks band: This is the band on the left side of a folder that we are talking about in this article. It contains items like Folder Tasks and Other places.
  • Expando: This is the name Microsoft uses for the controls you find in the tasks band. They contain a title and a subsection that can be expanded or collapsed.
  • Folder tasks: This is one of the sections in the tasks band. The title is usually "Folder Tasks" of "File and Folder Tasks". It contains standard items like Copy, Delete.
  • Extra tasks: This is an optional section that has a different color for the title, and sometimes an icon next to the title. The title can be for example "Picture Tasks".
  • Task Item: This is an individual command that appears in one of the expandos, such as Copy, Delete.

The callback message SFVM_GET_WEBVIEW_CONTENT

This is where it all starts. This new message is defined as follows:

C++
#define SFVM_GET_WEBVIEW_CONTENT 83

This callback message is passed to the callback function or interface you supplied in SHCreateShellFolderView(Ex).

The wParam in this message can be ignored. The lParam is a pointer to a SFVM_WEBVIEW_CONTENT_DATA struct, defined as follows:

C++
struct SFVM_WEBVIEW_CONTENT_DATA
{
    long l1;
    long l2;
    IUIElement *pUIElement1;
    IUIElement *pUIElement2;
    IEnumIDList *pEnum;
};

The first 2 members of this structure should be set to 0. It is possible that they can be used for something, but I didn't succeed in finding out what.

The IUIElement members represent the titles of the task sections: One for "Picture Tasks" and the like, and one for "Folder Tasks".

The last member is used for the "Related Places" section.

Manipulating the Related Places

This is the easiest part. It is regulated by the pEnum member. If you want Explorer to supply some related places for you, set this member to NULL. If you want to supply your own links, return an IEnumIDList interface. You know this interface from the enumeration of your folders. But this version will behave a bit different: You now enumerate the full PIDLs of the folders you want to list.

Supplying the title for your expandos

The IUIElement members of the struct are used to supply the titles of the expandos.

The first one is used for the extra tasks, the second one for the folder tasks.

Set the corresponding pointer to NULL for an expando you don't need.

Supply an IUElement interface for the expandos you do want to show. Let's take a look at this interface.

The interface IUIElement

This interface is fairly simple. It has functions to supply the title, tooltip and icon. You can let these vary with the selected items: Every time the selection changes, the functions to retrieve these values will be called again.

The interface is defined as follows:

C++
#undef  INTERFACE
#define INTERFACE   IUIElement

DECLARE_INTERFACE_(IUIElement, IUnknown)
{
    // IUnknown methods
    STDMETHOD(QueryInterface)(THIS_ REFIID riid, 
                            LPVOID FAR* ppvObj) PURE;
    STDMETHOD_(ULONG,AddRef)(THIS)  PURE;
    STDMETHOD_(ULONG,Release)(THIS) PURE;

    // IUIElement methods
    STDMETHOD(get_Name)(THIS_ IShellItemArray *pItemArray, 
                                      BSTR *bstrName) PURE;
    STDMETHOD(get_Icon)(THIS_ IShellItemArray *pItemArray, 
                                      BSTR *bstrName) PURE;
    STDMETHOD(get_Tooltip)(THIS_ IShellItemArray *pItemArray, 
                                      BSTR *bstrName) PURE;
};

typedef IUIElement FAR* LPUIELEMENT;

Looks pretty simple, huh? Of course you return the name in get_Name. The only odd thing is how you allocate the string: You allocate it with CoMemTaskAlloc.

But what is this IShellItemArray interface? It's an interface that lets you retrieve the items that are selected.

The interface IShellItemArray

The interface IShellItemArray is very similar to the interface IShellItem.

It is defined as follows:

C++
#undef  INTERFACE
#define INTERFACE   IShellItemArray

DECLARE_INTERFACE_(IShellItemArray, IUnknown)
{
    // IUnknown methods
    STDMETHOD(QueryInterface)(THIS_ REFIID riid, LPVOID FAR* ppvObj) PURE;
    STDMETHOD_(ULONG,AddRef)(THIS)  PURE;
    STDMETHOD_(ULONG,Release)(THIS) PURE;

    // IShellItemArray methods
    STDMETHOD(BindToHandler)(THIS_ IBindCtx *pbc, 
      REFGUID rbhid, REFIID riid, void **ppvOut)PURE;
    STDMETHOD(GetAttrributes)(int nEnum, 
      DWORD dwRequested, DWORD *pdwResult) PURE;
    STDMETHOD(GetCount)(UINT *pCount) PURE;
    STDMETHOD(GetItemAt)(UINT nIndex, 
      IShellItem **ppItem) PURE;
    STDMETHOD(EnumItems)(IEnumShellItems **) PURE;
};

typedef IShellItemArray FAR* LPSHELLITEMARRAY;

The normal way to get the items from this interface is by requesting an IDataObject interface. From this interface you can get the CFSTR_SHELLIDLIST data, which contains the PIDLs.

You can obtain an IDataObject interface by calling BindToHandler(NULL, BHID_DataObject, IID_IDataObject, (LPVOID *)&pDataObject). The GUID BHID_DataObject is defined as follows:

C++
DEFINE_GUID(BHID_DataObject, 0xb8c0bd9f, 0xed24, 0x455c, 
    0x83, 0xe6, 0xd5, 0x39, 0x0c, 0x4f, 0xe8, 0xc4);

The callback message SFVM_GET_WEBVIEW_TASKS

Now that we have found a way to define the expandos, we will also need a way to define the task items contained in them.

For this, we need a second callback message: SFVM_GET_WEBVIEW_TASKS.

This callback message is defined as follows:

C++
#define SFVM_GET_WEBVIEW_TASKS 84

The wParam can be ignored. The lParam is a pointer to a SFVM_WEBVIEW_TASKSECTION_DATA struct, defined as follows:

C++
struct SFVM_WEBVIEW_TASKSECTION_DATA
{
    IEnumUICommand *pEnum1;
    IEnumUICommand *pEnum2;
};

Again, the first member is for the Extra Tasks, the second one for the Folder Tasks.

The requested interfaces are standard enumerators for the type IUICommand. This enumerator is defined as follows:

C++
#undef  INTERFACE
#define INTERFACE   IEnumUICommand

DECLARE_INTERFACE_(IEnumUICommand, IUnknown)
{
    // IUnknown methods
    STDMETHOD(QueryInterface)(THIS_ REFIID riid, LPVOID FAR* ppvObj) PURE;
    STDMETHOD_(ULONG,AddRef)(THIS)  PURE;
    STDMETHOD_(ULONG,Release)(THIS) PURE;

    // *** IEnumUICommand methods ***
    STDMETHOD(Next)  (THIS_ ULONG celt,
                      LPUICOMMAND *rgelt,
                      ULONG *pceltFetched) PURE;
    STDMETHOD(Skip)  (THIS_ ULONG celt) PURE;
    STDMETHOD(Reset) (THIS) PURE;
    STDMETHOD(Clone) (THIS_ IEnumUICommand **ppenum) PURE;
};

As you might have guessed, every IUICommand represents one task item. Make sure to implement the method Reset, because your enumerator will be reused every time the selection changes.

The interface IUICommand

We are almost there now. All we need to do is define one more COM interface.

The interface IUICommand is an extension of IUIElement. It is defined as follows:

C++
#undef  INTERFACE
#define INTERFACE   IUICommand

DECLARE_INTERFACE_(IUICommand, IUIElement)
{
    // IUnknown methods
    STDMETHOD(QueryInterface)(THIS_ REFIID riid, LPVOID FAR* ppvObj) PURE;
    STDMETHOD_(ULONG,AddRef)(THIS)  PURE;
    STDMETHOD_(ULONG,Release)(THIS) PURE;

    // IUIElement methods
    STDMETHOD(get_Name)(THIS_ IShellItemArray *pItemArray, 
                                      BSTR *bstrName) PURE;
    STDMETHOD(get_Icon)(THIS_ IShellItemArray *pItemArray, 
                                      BSTR *bstrName) PURE;
    STDMETHOD(get_Tooltip)(THIS_ IShellItemArray *pItemArray, 
                                      BSTR *bstrName) PURE;

    // IUICommand methods
    STDMETHOD(get_CanonicalName)(THIS_ GUID *pGuid) PURE;
    STDMETHOD(get_State)(THIS_ IShellItemArray *pItemArray, 
                  int nRequested, enum UISTATE *pState) PURE;
    STDMETHOD(Invoke)(THIS_ IShellItemArray *pItemArray, 
                                        IBindCtx *pCtx) PURE;
};

typedef IUICommand FAR* LPUICOMMAND;

We already know most things about this interface. IShellItemArray has already been defined, all the rest is known stuff, except for the UISTATE enumeration.

I don't know the official values for this enum. All I know is that 0 means show this verb, and anything else means hide this verb.

Supplying icons

Of course, you supply the icons for the task items in get_Icon. The only question is what format they should be in.

Well, very simple: They take the form module.dll,-id.

Just like all the other strings, this string is allocated with CoTaskMemAlloc.

Further issues

You should now have a basic understanding of the task items and how to manipulate them. But there may be a few more things that need clarification.

Showing and hiding verbs

In your enumerator, you should always return all the task items.

If an item should not be shown for the selected PIDLs, you should indicate this in get_State. If all tasks are hidden, the expando will also be hidden.

Invoking the task

When the user clicks on a task, as you expect, the function Invoke will be called.

Be careful to retrieve the items using the method I described. This is the only way to make sure the result is correct.

Changing names

You can return a different name depending on the selected items.

Usually, the titles get different names: For example, "Folder Tasks" if no items are selected, "File and Folder Tasks" if at least one item is selected.

The task items themselves usually don't get different names. If you want to provide different tasks depending on the selected items, return all items in your enumerator and hide the ones that are not valid for this set of items.

IID values

You will need these for your QueryInterface implementation.

C++
// {EC6FE84F-DC14-4FBB-889F-EA50FE27FE0F}
DEFINE_GUID(IID_IUIElement,
    0xEC6FE84F,0xDC14,0x4FBB,0x88,0x9F,0xEA,0x50,0xFE,0x27,0xFE,0x0F);

// {4026DFB9-7691-4142-B71C-DCF08EA4DD9C}
DEFINE_GUID(IID_IUICommand,
    0x4026DFB9,0x7691,0x4142,0xB7,0x1C,0xDC,0xF0,0x8E,0xA4,0xDD,0x9C);

// {869447DA-9F84-4E2A-B92D-00642DC8A911}
DEFINE_GUID(IID_IEnumUICommand,
    0x869447DA,0x9F84,0x4E2A,0xB9,0x2D,0x00,0x64,0x2D,0xC8,0xA9,0x11);

All the definitions

The interfaces, structs and other definitions used in this article will be made available in the new version of shlext.h, which can be found here.

A Delphi version will be made available here.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


Written By
Web Developer
Belgium Belgium
Henk studied computer science at the University of Ghent, specializing in theoretical computer science.
He is now working for Artwork Systems, Belgium, and Whirling Dervishes Software, Belgium.
Henk knows a little something about networking, graphics, object-oriented design, AI, embedded systems. He knows most of the PDF specs by heart.
Henk developed NSELib, the NameSpace Extension Library.
You can find his latest freeware software at regxplor.com. It contains a namespace extension that puts the registry in Windows Explorer. The newest commercial project is Alpha ZIP, an explorer-embedded ZIP file utility.

Comments and Discussions

 
GeneralDefinition of SFVM_WEBVIEW_TASKSECTION_DATA is wrong Pin
Timo Kunze2-Sep-07 13:51
Timo Kunze2-Sep-07 13:51 
QuestionHow to link IID_IUICommand and other stuff Pin
alexej_zarva20-Mar-06 5:13
alexej_zarva20-Mar-06 5:13 
GeneralHelp Me!!! Pin
liugd3-Mar-06 2:05
liugd3-Mar-06 2:05 
GeneralCritical Mistake! Pin
jhjhjhjhjhjh9-Oct-05 23:58
jhjhjhjhjhjh9-Oct-05 23:58 
GeneralAwesome article Pin
Msftone19-Nov-03 11:29
Msftone19-Nov-03 11:29 
GeneralRe: Awesome article Pin
Henk Devos19-Nov-03 11:52
Henk Devos19-Nov-03 11:52 
GeneralRe: Awesome article Pin
Msftone19-Nov-03 11:54
Msftone19-Nov-03 11:54 
GeneralGreat! Pin
Hofver2-Jun-03 21:15
Hofver2-Jun-03 21:15 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.