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

Namespace extensions - the undocumented Windows Shell

Rate me:
Please Sign up or sign in to vote.
4.98/5 (32 votes)
30 Nov 199925 min read 524K   3.9K   169   84
This article explains how you can easily create a namespace extension with lots of features without doing lots of work by using some undocumented shell functions.

Index

Functions

<menu>
  • IsInterfaceSupported
  • PrintInterfaceName
  • PrintSupportedInterfaces
  • SHAlloc
  • SHCreateShellFolderViewEx
  • ShlExtInit
  • ShlExtUninit
  • SHShellFolderView_Message
  • ILAppendID
  • ILClone
  • ILCloneFirst
  • ILCombine
  • ILCreate
  • ILCreateFromPath
  • ILGetCount
  • ILGetDisplayName
  • ILGetNext
  • ILGetSize
  • ILGlobalClone
  • ILGlobalFree
  • ILFindChild
  • ILFindLastID
  • ILFree
  • ILIsEqual
  • ILIsParent
  • ILLoadFromStream
  • ILRemoveLastID
  • ILSaveToStream
  • Structures

    <menu>
  • SFVCB_COLUMNINFOSTRUCT
  • SFVCB_SELECTINFO
  • SFVCB_TOOLBARBUTTONINFO
  • SFVCB_TOOLBARINFO
  • SHColInfo
  • SHELLVIEWDATA
  • SHCreateShellFolderViewEx callback messages

    <menu>
  • SFVCB_ADDTOOLBARITEMS
  • SFVCB_CHANGENOTIFY
  • SFVCB_COLUMNCLICK
  • SFVCB_COLUMNCLICK2
  • SFVCB_COPYHOOKCALLBACK
  • SFVCB_DRAWMENUITEM
  • SFVCB_EXITMENULOOP
  • SFVCB_GETCHANGENOTIFYPIDL
  • SFVCB_GETDETAILSOF
  • SFVCB_GETNAMELENGTH
  • SFVCB_GETTOOLBARTIP
  • SFVCB_GETTOOLBARINFO
  • SFVCB_INITMENUPOPUP
  • SFVCB_INVOKECOMMAND
  • SFVCB_LISTREFRESHED
  • SFVCB_MEASUREMENUITEM
  • SFVCB_REGISTERCOPYHOOK
  • SFVCB_SELECTIONCHANGED
  • SFVCB_VIEWRELEASE
  • SFVCB_WINDOWCLOSING
  • SFVCB_WINDOWCREATED
  • SFVCB_WINDOWFOCUSED
  • SHShellFolderView_Message messages

    <menu>
  • SFVM_GETARRANGECOLUMN
  • SFVM_ADDOBJECT
  • SFVM_GETITEMCOUNT
  • SFVM_GETITEMPIDL
  • SFVM_REMOVEOBJECT
  • SFVM_UPDATEOBJECT
  • SFVM_SETREDRAW
  • SFVM_GETSELECTEDOBJECTS
  • SFVM_ISDROPONSOURCE
  • SFVM_MOVEICONS
  • SFVM_GETDRAGPOINT
  • SFVM_GETDROPPOINT
  • SFVM_SETOBJECTPOS
  • SFVM_ISDROPONBACKGROUND
  • SFVM_CUTOBJECTS
  • SFVM_TOGGLEAUTOARRANGE
  • SFVM_LINEUPICONS
  • SFVM_GETAUTOARRANGE
  • SFVM_GETSELECTEDCOUNT
  • SFVM_GETITEMSPACING
  • SFVM_REFRESHOBJECT
  • SFVM_SETCLIPBOARDPOINTS
  • Shell Messages

    <menu>
  • CWM_GETISHELLBROWSER
  • CWM_GETPATH
  • CWM_GETSETCURRENTINFO
  • CWM_SELECTITEM
  • CWM_SETPATH
  • CWM_STATECHANGE
  • CWM_STOPWAITING
  • CWM_TESTPATH
  • CWM_WANTIDLE
  • Macros

    <menu>
  • FileCabinet_GetIShellBrowser
  • FileCabinet_GetSetCurrentInfo
  • FileCabinet_SelectItem
  • FileCabinet_StopWaiting
  • FileCabinet_WantIdle
  • Interfaces

    <menu>
  • IShellDetails <menu>
  • GetDetailsOf
  • ColumnClick

  • This article explains how you can easily create a namespace extension with lots of features without doing lots of work by using some undocumented shell functions. The most noticeable function is SHCreateShellFolderViewEx, which creates the view for you and creates all interfaces you need for displaying the contents of your folder. You can modify the behaviour of the folder by implementing a callback function. This is how Microsoft implements its own namespace extensions.

    Introduction to the windows shell

    The windows shell is built around COM interfaces. The browser ("explorer") calls interfaces that are implemented by a number of DLL's and these DLL's can call back into the interfaces of the browser. You can extend the behaviour of the browser by plugging in your own DLL that implements the needed interfaces.

    The householding of the DLL's is maintained in the registry, as is usual for COM objects.

    The shell namespace

    The shell namespace is a collection of folders that contain items. These items can in turn be folders, generating a tree structure. This ressembles the directory tree structure that is found in a file system, but should not be confused with it.

    The top of the shell namespace tree is the Desktop folder. This folder contains "my computer", which in turn contains the drives on your computer. The part of the shell namespace that represents a drive looks almost the same as the directory structure on that drive, but is not exactly the same. The drive can contain additional items and existing items may look very different in the shell namespace.

    Shell extensions

    The DLL's that are plugged into the shell are called shell extensions. There are several kinds of shell extensions:

    1. A context menu extension puts extra items in the context menu that is viewed in the browser.
    2. A property sheet extension displays extra property pages in the property sheets that are viewed in the browser.
    3. A namespace extension adds extra folders to the namespace.

    Pidls

    Every item in a folder is identified by an identifier, just like every file or directory on a drive is identified by a filename. This identifier is called a Pidl.

    For someone who uses the shell to browse the namespace, a pidl is just an opaque structure that gets passed around without having any meaning.

    Someone who implements a part of the namespace assigns a meaning to the pidls for his part of the namespace. The pidl is a variable-sized structure that can contain anything the implementor wants to put in. The pidl usually caches all information that is frequently needed. In a directory structure, the pidl contains the long and short filename and some other stuff.

    Structure of a pidl

    A item id consists of 2 parts: the length and the data. The length comes first and is the total length of the item (including the length part itself). The data is opaque to the user and only has meaning to the implementor of the namespace.

    Multiple item ids are concatenated to form a pidl. A pidl is a series of concatenated item ids, ending with an id with length 0.

    Absolute and relative pidls

    A filename can be absolute or relative: An absulute filename is fully qualified (e.g. <nobr>"c:\winnt\system32\shell32.dll"). A relative filename is relative to the directory in which it resides.

    The same goes for a pidl. A pidl can be absolute or relative. The root for an absolute pidl is the desktop. A relative pidl is relative to a specific folder in the namespace.

    Designing your pidls

    If you implement your own namespace extension, you will have to design your own pidls.

    The easiest way to assign a meaning to your pidls is by defining a struct that contains all the information you need.

    You must be able to determine if a pidl that is passed to you is really a valid pidl. You can do this by starting the pidl with a signature (a few bytes that are always the same).

    The pidl should contain all information that will frequently be needed and that takes some time to find out. You should always store the name and all texts that are stored in the different columns in the details view, unless you can derive them easily.

    Your pidl should contain one field that uniquely identifies the item. This can be a handle, an ID,...

    You will be the only one who decides wether two pidls are for the same item. You will do that through your IShellFolder's CompareIDs. Return 0 for pidls that represent the same object, and 1 or -1 for pidls that represent different objects (even if you don't care how they are sorted).

    Allocating and freeing pidls

    All pidls should always be allocated and freeed by the Shell Allocater.

    You can retrieve the Shell Allocator by calling SHGetMalloc.

    Shortcuts for allocating and freeing pidls are provided by the functions SHAlloc and ILFree.

    Pidl functions

    SHAlloc

    WINSHELLAPI LPVOID WINAPI SHAlloc(UINT cb);

    Description

    Allocates cb bytes of memory using the Shell Allocator

    Parameters

    • cb: The size in bytes of the block to be allocated

    Return value

    A pointer to the block of memory that was allocated

    ILFree

    WINSHELLAPI void WINAPI ILFree(LPITEMIDLIST pidl);

    Description

    Frees a pidl using the Shell Allocator

    Parameters

    • pidl: the pidl to free

    Remarks

    I have no idea why there is both a SHfree function and an ILFree function. They are probably exactly the same.

    ILClone

    WINSHELLAPI LPITEMIDLIST WINAPI ILClone(LPCITEMIDLIST pidl);

    Description

    Creates a copy of the passed in pidl

    Parameters

    • pidl: The pidl to copy

    Return value

    A pointer to the newly created copy of the pidl

    Remarks

    The new pidl is allocated using the Shell Allocator. You should free it by calling ILFree.

    ILAppendID

    WINSHELLAPI LPITEMIDLIST WINAPI ILAppendID(LPITEMIDLIST pidl,
                                               LPCITEMIDLIST item,BOOL bEnd);

    Description

    Appends a new item identifier to an existing pidl


    Parameters

    • pidl: A complex pidl to which an extra item id will be added
    • item: A simple pidl that constists of only one item
    • bEnd: If non-zero, the item is added at the end. If zero, the item is added to the beginning.

    Remarks

    This function destroys the passed in complex pidl.

    ILCloneFirst

    WINSHELLAPI LPITEMIDLIST WINAPI ILCloneFirst(LPCITEMIDLIST pidl);

    Description

    Creates a new pidl that contains the first item id of a complex pidl

    Parameters

    • pidl: The complex pidl from which to extract the first item id

    Return value

    A newly created pidl that contains the first item id of the passed in complex pidl

    Remarks

    The new pidl is allocated with the Shell Allocator. You should free it by calling ILFree.

    ILCombine

    WINSHELLAPI LPITEMIDLIST WINAPI ILCombine(LPCITEMIDLIST pidl,
                                              LPCITEMIDLIST pidlsub);

    Description

    Concatenates two complex pidls

    Parameters

    • pidl: The left part of the pidl
    • pidlsub: the right part of the pidl

    Return value

    The newly created pidl


    Remarks

    The passed in pidls are not destroyed. The newly created pidl is allocated using the Shell Allocator. You should free it by calling ILFree. This function is useful if you have a relative pidl of an item and the absolute pidl of its parent folder. The function returns the absolute pidl of the item.

    ILCreateFromPath

    Remarks

    I didn't find out the exact signature of this function yet.

    ILFindChild

    WINSHELLAPI LPITEMIDLIST WINAPI ILFindChild(LPCITEMIDLIST pidl1,
                                                LPCITEMIDLIST pidl2);

    Description

    Compares the elements of a complex pidl

    Parameters

    • pidl1: the first pidl
    • pidl2: the second pidl

    Return value

    If at least the first item id is the same, returns the location of the first item id in pidl2 that doesn't match pidl1. NULL if pidl2 is shorter than pidl1

    Remarks

    I never tested this function. The signature and description may not be correct.

    ILFindLastID

    WINSHELLAPI LPITEMIDLIST WINAPI ILFindLastID)(LPCITEMIDLIST pidl);

    Description

    Finds the position of the last item id in a pidl

    Parameters

    • pidl: A complex pidl

    Return value

    A pointer to the last item id in the passed in pidl

    Remarks

    You can call ILClone(ILFindLastID(pidl)) to create a relative pidl out of an absolute pidl.

    ILGetDisplayName

    Remarks

    I didn't find out the exact signature of this function yet.

    ILGetNext

    WINSHELLAPI LPITEMIDLIST WINAPI ILGetNext(LPCITEMIDLIST pidl);

    Description

    This function finds the location of the second item id in a complex pidl

    Parameters

    • pidl: A complex pidl

    Return value

    The position of the next item id in the pidl The pidl itself is the first item id, the next one is the second.

    Remarks

    You can use ILClone(ILFindNextID(pidl)) to obtain a pidl of an item that is relative to the first parent folder. This can be very useful if you were passed a complex pidl in you IShellFolder implementation. You can split off the first item id, bind a new shell folder to this id and the,n pass this new folder the remainder of the pidl.

    ILGetSize

    WINSHELLAPI UINT WINAPI ILGetSize(LPCITEMIDLIST pidl);

    Description

    Calculates the full size of a pidl

    Parameters

    • pidl: The complex pidl of which to calculate the size

    Return value

    The total size of the passed in pidl in bytes, including the zero terminator

    ILGlobalClone

    Remarks

    I didn't find out the exact signature of this function yet.

    ILGlobalFree

    Remarks

    I didn't find out the exact signature of this function yet.

    ILIsEqual

    WINSHELLAPI BOOL WINAPI ILIsEqual(LPCITEMIDLIST pidl1, LPCITEMIDLIST pidl2);

    Description

    Tests two pidls for equality

    Paramaters

    • pidl1: The first pidl
    • pidl2: The second pidl

    Return value

    Zero if the two pidls are different, nonzero if the pidls are equal

    ILIsParent

    Remarks

    I didn't find out the exact signature of this function yet.

    ILLoadFromStream

    Remarks

    I didn't find out the exact signature of this function yet.

    ILRemoveLastID

    WINSHELLAPI BOOL WINAPI ILRemoveLastID(LPCITEMIDLIST pidl);

    Description

    Removes the last item identifier from a complex pidl

    Parameters

    • pidl: A complex item identifier list

    Return value

    Nonzero if successful, zero otherwise

    Remarks

    This function modifies the passed in pidl by setting the last item id's byte count to zero.
    To create a new pidl without the last item id, you would have to call ILRemoveLastID(ILClone(pidl)).

    ILSaveToStream

    Remarks

    I didn't find out the exact signature of this function yet.

    Object model

    The shell is browsed by a Shell Browser object, which is implemented by the browser, usually Windows Explorer. This browser traverses the namespace.

    The namespace is made up of Shell Folders. A Shell Folder is an object that represents a virtual folder, i.e. a filesystem directory or a namespace extension folder. The items of a Shell Folder are enumerated by an Item Enumerator. This object simply enumerates the pidls of objects.

    The contents of a Shell Folder are viewed by a Shell View. The Shell View is a window that usually displays a list of items. A group of items (e.g. the items that are selected in a Shell View) is represented by a UI Object.

    The Shell Browser

    The Shell Browser is the application that browses the namespace (Windows Explorer). The Shell Browser implements the interface IShellBrwoser. You will never implement this interface yourself.

    Shell Folders

    Shell Folders represent folders in the namespace. They create new Shell Folders for their items and they create UI Objects. They provide information on their items. A Shell Folder implements a namespace extension.

    Interfaces implemented by Shell Folders

    A shell folder should implement IShellFolder, IPersistFolder, IDropTarget, IExtractIcon and <A href="#IShellDetails">IShellDetails</A>.

    The IShellFolder interface is used for getting information on items in a folder and as a factory for creating Item Enumerators, Shell Views and UI Objects. Most IShellFolder methods take pidls as parameters. These pidls are always relative to the Shell Folder.

    The IPersistfolder interface is only used to pass the shell folder its own absolute pidl.

    The IDropTarget interface is a standard OLE interface that is used for drag and drop.

    The IExtractIcon interface is used to get the icon for an item.

    The <A href="#IShellDetails">IShellDetails</A> interface is used for communication with the Shell View. It provides some extra information about how to display items in a multi-column list: the titles for the columns and the details to fill in in these columns.

    All these interfaces are well documented, except <A href="#IShellDetails">IShellDetails</A>. This interface is described later.

    Item Enumerators

    An item enumerator makes it possible to enumerate all items in a Shell Folder.

    An Item Enumerator implements IEnumIDList. This is a common IEnumXXX interface. This interface is well documented.

    User Interface Objects (UI objects)

    UI Objects handle user interaction with items. They implement shell extensions other than namespace extensions.

    Possible UI objects are context menu handlers, property sheet handlers, infotip handlers.

    UI Objects must be able to handle multiple selection.

    Interfaces implemented by UI Objects

    UI Objects implement some are all of the following interfaces:
    IObjectWithSite, IExternalConnection, IShellExtInit, IDataSource, IContextMenu, IShellPropSheetExt and IQueryInfo.

    IObjectWithSite is a standard OLE interface that is used for setting up communication between an object and the container in which it resides. In this case the container is the Shell Browser. You can omit thhis interface.

    IExternalConnection is used for maintaining strong locks on an object. This interface is needed because the object may be marshalled to another proces (e.g. during drag and drop).
    You can omit this interface. In that case, OLE will provide a default interface for you.

    IShellExtInit is implemented by property sheet handlers and context menu handlers. These should always implement the interface. The IShellExtInit interface only has one method Initialize, which is used for setting the context of the shell extension.

    IDataSource is a standard OLE interface. It is used mainly for drag and drop and for copy and paste. You can think of the IDataSource interface as a way of serializing the set of items.
    If your namespace extension has more than one folder, you can implement your own clip formats. The IDataSource interface is too complex to be fully covered here.

    Besides its obvious usage as a source of information for displaying a context menu, the IContextMenu interface is used for some other purposes: When the user presses a standard button in the toolbar, IContextMenu::InvokeCommand will be invoked with a verb. This verb will be a word like cut, copy, paste, delete or properties.

    The IContextMenu interface is also used to add items to the main menu of the browser's window. When QueryContextMenu is called, you should add commands to the menu that have identifiers of the form idCmdFirst + SOME_CONSTANT. When InvokeCommand is called, the identifier SOME_CONSTANT will be passed.

    The IShellPropSheetExt interface is used for displaying property pages.

    The IQueryInfo interface is used for displaying info tips when the mouse is moved over an item.

    All these interfaces are well documented.

    Shell Views

    Shell views are the windows that display a shell folder's contents. Shell views implement IShellView and some additional interfaces. Instead of implementing this object yourself, you should call <A href="#SHCreateShellFolderViewEx">SHCreateShellFolderViewEx</A>. This function creates the Shell View for you.

    Interface IShellDetails

    Besides the IUnknown functions, the IShellDetails interface has two functions: GetDetailsOf and ColumnClick.
    <A name=IShellDetails_GetDetailsOf></A>HRESULT STDMETHODCALLTYPE GetDetailsOf(LPCITEMIDLIST pidl, UINT col, 
                                           <A href="#SHColInfo">SHColInfo</A> *data);

    Description

    If pidl equals NULL, this function retrieves information about a column in the Shell View. Otherwise, it retrieves the information to display in a particular column of the view for a given pidl.

    Parameters

    • pidl: The identifier of the item for which to retrieve information, or NULL to retrieve information for a whole column.
    • col: The index of the column (starting at 0)
    • data: Pointer to the SHColInfo struct to be filled in

    Return value

    Return S_OK if you filled in the details, E_FAIL otherwise.
    If pidl equals NULL, you should return S_OK for all columns that you support and E_FAIL for an index that is too large. This is how the Shell View will know how many columns to display.

    <A name=IShellDetails_ColumnClick></A>HRESULT STDMETHODCALLTYPE ColumnClick(UINT col);

    Description

    This function is called when the user clicks the title of a column.

    Parameters

    • col: The index of the column that was clicked (starting at 0)

    Remarks

    You should send a SFVM_REARRANGE message to the owner of the view window.
    You can use the function SHShellFolderView_Message to send the meassage. The window handle of the owner of the view window is passed to you in IShellFolder::CreateViewObject. This is the time to save this handle.
    The lparam that you should pass to SHShellFolderView_Message is the index of the column that was clicked (i.e. the col parameter).
    After calling SHSHellFolderView_Message, IShellFolder::CompareIDs will be called with an lParam that equals the index of the column that was clicked. This is contrary to the Microsoft documentation, which states that this lParam will always be zero and should be ignored.

    Function SHCreateShellFolderViewEx

    The function

    WINSHELLAPI HRESULT WINAPI SHCreateShellFolderViewEx(<A href="#SHELLVIEWDATA">LPSHELLVIEWDATA</A> psvcbi, 
                                                         LPVOID *ppv);

    Description

    This is the most interesting function I discovered. This function enables you to use the same mechanism as Microsoft for displaying the contents of your namespace extensions.

    This function creates the Shell View for you, including the most important interfaces like IShellView.

    This function makes sure you will handle everything the way you should. It provides an easy interface for otherwise difficult tasks like changing the toolbar.

    When calling this function, you pass a callback function that gets called to handle all kinds of events, enabling you to customize the shell view.

    Parameters

    • psvcbi: Pointer to a SHELLVIEWDATA structure
    • ppv: Receives a pointer to the Shell View's IUnknown.

    Remarks

    Call this function from your IShellFolder's CreateViewObject when riid is IID_IShellView.

    The SHELLVIEWDATA structure

    typedef struct _SHELLVIEWDATA
    {
        DWORD           dwSize;
        LPSHELLFOLDER   pShellFolder;
        DWORD           dwUserParam;
        LPCITEMIDLIST   pidl;
        DWORD           dwEventId;
        SHELLVIEWPROC   pCallBack;
        DWORD           viewmode;  // NF_* enum
    } SHELLVIEWDATA, * LPSHELLVIEWDATA;

    Members:

    • dwSize: sizeof(SHELLVIEWDATA)
    • pShellFolder: Pointer to the shell folder that is creating a view object
    • dwUserParam: A user-defined value that will be passed back in the callback function
    • pidl: The absolute pidl of the folder that is being viewed
    • dwEventId: any combination of the SHCNE_ constants as described in the SHChangeNotify function. These are the notifications that should be handled by the view object.
    • pCallback: Pointer to your callback function (described later)
    • viewmode: NF_INHERITVIEW or NF_LOCALVIEW

    The callback function

    HRESULT CALLBACK SHELLVIEWPROC(DWORD dwUserParam, LPSHELLFOLDER psf, 
                                   HWND hwnd, UINT uMsg,
                                   WPARAM wParam, LPARAM lParam);

    Description

    This is the prototype of a function you should implement yourself. You pass a pointer to this function in SHCreateShellFolderViewEx.

    Parameters

    • dwUserParam: a user-defined value that was passed in SHCreateShellFolderViewEx
    • psf: Pointer to the shell folder that this view object is displaying
    • hwnd: The window handle of the view. This is not the same as the owner of the window that was passed in CreateViewObject. This owner is actually the parent of the view window. All messages are always sent to this owner window, so i don't really see the use of this hwnd parameter.
    • uMsg: one of the constants that are defined below (or yet another one)
    • wParam: dependent on uMsg
    • lParam: dependent on uMsg

    Remarks

    This is the function that enables you to modify the behavior of the shell view. You can add toolbar buttons, change the menu and react on several events, all from within this function. This function is typically a large switch on uMsg. Te values for uMsg and the corresponding wParam and lParam are described below. The uMsg values all have a name that starts with SFVCB_.

    SFVCB_INVOKECOMMAND

    Description

    This message is sent when the user presses one of the toolbar buttons that you added.

    wParam

    The wParam value is the command id that you assigned to this toolbar button. Maybe you should use LOWORD(wParam).

    SFVCB_GETTOOLBARTIP

    Description

    This message is sent either when a tooltip is needed for a toolbar button or when a text label is needed if the toolbar displays text labels beneath the buttons.

    LOWORD(wParam)

    This is the command ID, like in SFVCB_INVOKECOMMAND.

    lParam

    lParam is a pointer to a unicode buffer that will receive the text string.

    HIWORD(wParam)

    This is the length of the buffer in unicode characters.

    Remarks

    You will typically call Lo<NOBR>adStringW(hInstance, ID_YOUR_COMMAND, (LPSTR)lParam, <BR>HIWORD(wParam))</NOBR> to react on this message.

    SFVCB_GETTOOLBARINFO

    Description

    This message allows you to change the toolbar. It is sent when the list view is first shown.

    lParam

    Pointer to a SFVCB_TOOLBARINFO structure to be filled in.

    Remarks

    If you return S_OK, you will get a SFVCB_ADDTOOLBARITEMS message that allows you to provide the details of the buttons.

    SFVCB_ADDTOOLBARITEMS

    Description

    This message is sent if you return S_OK to the SFVCB_GETTOOLBARINFO message. It is sent once to fill in details for all buttons.

    LOWORD(wParam)

    This is a constant you should add to your command IDs, much like in IContextMenu. When the user presses a toolbar button, you will receive the ID you filled in minus this constant.

    lParam

    Pointer to an array of SFVCB_TOOLBARBUTTONINFO structures. The size of the array is equal to the number of buttons that was supplied in SFVCB_GETTOOLBARINFO.

    SFVCB_INITMENUPOPUP

    Description

    I don't know the exact meaning of this message.

    SFVCB_SELECTIONCHANGED

    Description

    This message is sent when the selection changes in the list view.

    lParam

    Pointer to a SFVCB_SELECTINFO structure.

    Remarks

    If the user selects/deselects multiple items at a time (e.g. using Shift), the message will be sent for every item.

    SFVCB_DRAWMENUITEM

    Description

    I don't know the exact meaning of this message.

    SFVCB_MEASUREMENUITEM

    Description

    I don't know the exact meaning of this message.

    SFVCB_EXITMENULOOP

    Description

    I don't know the exact meaning of this message.

    SFVCB_VIEWRELEASE

    Description

    I don't know the exact meaning of this message.

    SFVCB_GETNAMELENGTH

    Description

    I don't know the exact meaning of this message. The message is sent when beginning label edit.

    SFVCB_CHANGENOTIFY

    Description

    This message is sent when SHChangeNotify is called for one of the items in the shell folder that is represented by this view.

    wParam

    Pointer to an array of the two pidls that were passed to SHChangeNotify.

    lParam

    The dwEventID that represents the event (e.g. SHCNE_RENAMEITEM)

    SFVCB_WINDOWCREATED

    Description

    This message is sent when the window is created

    wParam

    The HWND of the newly created window

    SFVCB_WINDOWCLOSING

    Description

    I don't know the exact meaning of this message.

    SFVCB_LISTREFRESHED

    Description

    I don't know the exact meaning of this message.

    SFVCB_WINDOWFOCUSED

    Description

    This message is sent to inform you that the list view has received the focus.

    SFVCB_REGISTERCOPYHOOK

    Description

    I don't know the exact meaning of this message.

    SFVCB_COPYHOOKCALLBACK

    Description

    I don't know the exact meaning of this message.

    SFVCB_GETDETAILSOF

    Description

    This message is sent to if you don't implement IShellDetails.

    lParam

    Pointer to a SFVCB_COLUMNINFOSTRUCT structure. The STRRET has to be filled in.

    wParam

    The column for which the info is requested.

    Remarks

    The pidl in the SFVCB_COLUMNINFOSTRUCT structure will be NULL to request the title of a column.

    SFVCB_COLUMNCLICK

    Description

    This message is sent if you don't implement IShellDetails.

    wParam

    The index of the column that was clicked

    Remarks

    The default implementation would be SHShellFolderView_Message(hWndCabinet, SFVM_REARRANGE, wParam) where hWndCabinet is the window handle that was passes in IShellFolder::GetViewObjectOf.

    SFVCB_GETCHANGENOTIFYPIDL

    Description

    Use this message to change the pidl to watch for change notifications. This is only useful of you will call SHChangeNotify with another pidl than the one specified in SHCreateShellFolderViewEx.

    lParam

    Pointer to a complex pidl to be filled in

    Remarks

    It seems that specifying a NULL pidl is just the same as failing the message. You will probably never use this one.

    SFVCB_COLUMNCLICK2

    Description

    The same as SFVCB_COLUMNCLICK, but called when you do implement IShellDetails.

    Used structs

    SHColInfo

    typedef struct
    {
        DWORD   fJustify;
        INT    nWidth;
        STRRET    text;
    } SHColInfo, *PSHCOLINFO;

    SFVCB_COLUMNINFOSTRUCT

    typedef struct tag_SFVCB_COLUMNINFOSTRUCT
    {
      LPCITEMIDLIST pidl;
      SHColInfo    sci;
    } SFVCB_COLUMNINFOSTRUCT, *LPSFVCB_COLUMNINFOSTRUCT;

    SFVCB_TOOLBARINFO

    typedef struct tag_SFVCB_TOOLBARINFO
    {
        DWORD dwNumItems;
        DWORD dwPos;
    } SFVCB_TOOLBARINFO;

    SFVCB_TOOLBARBUTTONINFO

    typedef struct tag_SFVCB_TOOLBARBUTTONINFO
    {
        DWORD dwBitmap; //bitmap index
        DWORD dwCommand; // command id
        DWORD dwFlags; // 4 for normal button, 104 for separator
        DWORD reserved1; // 0
        DWORD reserved2; // -1
    } SFVCB_TOOLBARBUTTONINFO;

    SFVCB_SELECTINFO

    typedef struct tag_SFVCB_SELECTINFO
    {
        DWORD reserved; // 0
        DWORD dwFLAGS; //LVIS_SELECTED, LVIS_FOCUSED,...
        LPITEMIDLIST pidl;
    } SFVCB_SELECTINFO;

    The function SHShellFolderView_Message

    The function

    WINSHELLAPI int WINAPI SHShellFolderView_Message(HWND hwndCabinet, UINT uMsg, 
                                                     LPARAM lParam);

    Description

    This function can be used to send some special messages to the cabinet window. These messages have mostly to do with gatherring information about items and changing some attributes of some items.

    Parameters

    • hwndCabinet: The window handle that was passed in IShellFolder::CreateViewObject
    • uMsg: One of the SFVM_ constants that are described later
    • lParam: a message-dependant value

    Return value

    The return value depends on the message.

    Remarks

    You will need to call this function to enable sorting on a specified column. You use SFVM_REARRANGE for that.

    SFVM_REARRANGE

    This message indicates that the user has clicked a column in the header of the list control. The list needs to be rearranged.

    lParam

    The index of the column on which to sort (starting at 0). This value will be passes to IShellFolder::CompareIDs.

    SFVM_GETARRANGECOLUMN

    To be done.

    SFVM_ADDOBJECT

    To be done.

    SFVM_GETITEMCOUNT

    Description

    Used to retrieve the number of items in the list.

    Return value

    The number of items in the list

    SFVM_GETITEMPIDL

    To be done.

    SFVM_REMOVEOBJECT

    Description

    Use this message to remove an item from the list.

    lParam

    lParam is a relative pidl of the object to remove. You can specify NULL to remove all items.

    SFVM_UPDATEOBJECT

    To be done.

    SFVM_SETREDRAW

    To be done.

    SFVM_GETSELECTEDOBJECTS

    Description

    Use this message to retrieve an array of pidls for all selected objects.

    lParam

    lParam is actually of type (LPITEMID **). It is a pointer to a pointer that receives the address of an array of pidls. Use SFVM_GETSELECTEDCOUNT to learn the size of this array.

    SFVM_ISDROPONSOURCE

    To be done.

    SFVM_MOVEICONS

    To be done.

    SFVM_GETDRAGPOINT

    To be done.

    SFVM_GETDROPPOINT

    To be done.

    SFVM_SETOBJECTPOS

    To be done.

    SFVM_ISDROPONBACKGROUND

    To be done.

    SFVM_CUTOBJECTS

    To be done.

    SFVM_TOGGLEAUTOARRANGE

    To be done.

    SFVM_LINEUPICONS

    To be done.

    SFVM_GETAUTOARRANGE

    To be done.

    SFVM_GETSELECTEDCOUNT

    Description

    This message can be used to learn how many items are selected in the list.

    Return value

    The number of selected items

    SFVM_GETITEMSPACING

    To be done.

    SFVM_REFRESHOBJECT

    To be done.

    SFVM_SETCLIPBOARDPOINTS

    To be done.

    Shell messages

    There are some undocumented messages that can be sent to a cabinet window. This is again the window that is passed as hwndOwner in IShellFolder::CreateViewObject.

    CWM_SETPATH

    wParam

    A combination of one or more of the flags CSP_HANDLE and CSP_REPOST. CSP_REPOST indicates the message should not be handled immediately.

    lParam

    If CSP_HANDLE is specified, lParam is a HGLOBAL that contains a string. This memory will be freed when the message is handled.
    Otherwise, lParam points to a string.

    CWM_WANTIDLE

    Macro

    This message can be sent using the following macro:
    FileCabinet_WantIdle(_hwnd, _user, _lpidlproc)

    Description

    Use this message if you created a window using SHCreateShellFolderViewEx and you want to do idle processing in your window.

    wParam

    wParam (the _user in the macro) is a user-defined value that will be passed to the idle proc.

    lParam

    lParam (the _lpidlproc in the macro) is the idle proc that should be called. This function is of the type FCIDLEPROC.

    Return value

    non-zero if successful, zero otherwise

    CWM_GETSETCURRENTINFO

    Macro

    FileCabinet_GetSetCurrentInfo(_hwnd, _bSet, _lpfs)<BR>

    Description

    This message is used to retrieve or change the current folder settings.

    wParam

    wParam is the _bSet in the macro. If it is zero, the settings are being retrieved. Otherwise, they are being set.

    lParam

    lParam is the _lpfs in the macro. It points to a FOLDERSETTINGS structure that contains the values to set or receives the current values, depending on wParam.

    CWM_SELECTITEM

    Macro

    FileCabinet_SelectItem(_hwnd, _bSel, _lpidl)<BR><BR>

    Description

    Use this message to select/deselect an item.

    wParam

    wParam is the _bSel in the macro. If it is zero, the item is selected. Otherwise, the item is deselected.

    lParam

    lParam is the _lpidl in the macro. It is the pidl of the item to select/deselect. Use NULL to select/deselect all items.

    CWM_STOPWAITING

    Macro

    FileCabinet_StopWaiting(_hwnd)

    Remarks

    One source defines the same message as CWM_SELECTITEMSTR. I don't know which one is right.

    CWM_GETISHELLBROWSER

    Macro

    FileCabinet_GetIShellBrowser(_hwnd)

    Description

    Returns an IShellBrowser interface pointer of the shell browser that created the window.

    Remarks

    The returned IShellFolder interface is not AddRef'ed, so you should not call Release on the interface. This message is sent frequently by all microsoft namespace extensions and is the most important one. This message is described in the Microsoft Knowledge Base article Q157247.

    CWM_TESTPATH

    To be done.

    CWM_STATECHANGE

    To be done.

    CWM_GETPATH

    To be done.

    FCIDLEPROC

    typedef BOOL (CALLBACK *FCIDLEPROC)(void FAR *lpsv, UINT uID);

    Description

    This is the idle proc that will be called if you send CWM_WANTIDLE.

    Paramaeters

    • lpsv : pointer to the shell view that requested idle time processing
    • uID : the user-defined value that wass passen to CWM_WANTIDLE

    Return value

    Return non-zero if you want to continue idle time processing. The function will be called again.
    Return zero if your idle-time processing has finished.

    Remarks

    you should make this function as short as possible. To perform multiple tasks, process one atomic task in every call and return non-zero until all jobs are finished.

    Some helper functions

    ShlExtInit

    void ShlExtInit()

    Description

    Performs dynamic binding to the shell32 functions.

    ShlExtUninit

    void ShlExtUninit()

    Description

    Cleans up the dynamic binding that was set up by ShlExtInit.

    ILCreate

    LPITEMIDLIST ILCreate(LPVOID pData, DWORD dwLen)

    Description

    Allocates and initializes a simple pidl

    Parameters

    • pData: The item id to put in the pidl (without the header)
    • dwLen:The length of pData (in bytes)

    Return value

    The newly created pidl

    ILGetCount

    int ILGetCount(LPCITEMIDLIST pidl)

    Description

    calculates teh number of item IDs in a complex pidl

    Parameters

    • pidl: The comple pidl on which to perform the calculation

    Return value

    The number of item IDs that make up this complex pidl

    PrintInterfaceName

    void PrintInterfaceName(REFIID riid)

    Description

    Sends the name of an interface to the debugger
    Useful to trace QueryInterface calls

    Parameters

    • riid: The GUID of the interface for which to print the name

    IsInterfaceSupported

    BOOL IsInterfaceSupported(IUnknown *punk, REFIID riid)

    Description

    Determines wether an object supports a given interface

    Parameters

    • punk: The IUnknown of the object to test
    • REFIID: the GUID of the interface to test for

    Return value

    Non-zero if the interface is supported, zero otherwise.

    PrintSupportedInterfaces

    void PrintSupportedInterfaces(IUnknown *punk)

    Description

    Sends the names of all interfaces of an object to the debugger.
    When you receive an interface while debugging, this function can come in very handy.

    Parameters

    • punk: The IUnknown interface of the object for which to print the interfaces

    Implementing "View as Web Page"

    You don't have to do anything in your code to implement a web view. You only have to create your web page and link your class id to it in the registry.

    The web page

    You should base your web page on the web pages that are created by Microsoft. On windows NT, you can find them in the directory winnt\web. A typical example is folder.htt, the web page for a normal folder. Just copy this web page and edit it to suit your needs.
    There is one little problem: Microsoft changed the look of these web pages with every release of Windows, so you would have to provide separate web pages for all operating system versions.

    Registry enteries

    Explorer will rely on the class id that is returned by your IPersistFolder's GetClassID. As you know (and is very well documented), all information about your class is gathered in HKEY_CLASSES_ROOT\CLSID\{yourclassid}. There should already be a subkey shellex. In this shellex, you should create a subkey ExtShellFolderView, which again contains a subkey {5984FFE0-28D4-11CF-AE66-08002B2E1262}. In this subkey, you create an entry with the name PersistMoniker. It's value should be the full path of your web page.

    References

    Most of this stuff wasn't invented by me. You can find more information on the following locations: <menu>
  • The original ShlExt.h source
  • Undocumented Windows 95
  • Wine headquarters
  • You should also take a look at the shlext.h header file. It contains some information that is not included on this page.

    Feedback

    If you use the information on this page, you will probably discover things that are still missing here. You can see that there are lots of "to be done" bits. It is important to make that information available, so that you make the life of other developers a little easier. Please send me all your comments, sugestions and discoveries by email or leave comments on the codeproject site. All new discoveries will be available on my home page as soon as possible, and major updates will be posted on the codeproject site.

    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

     
    GeneralRe: sample Pin
    31-Jan-01 19:28
    suss31-Jan-01 19:28 
    GeneralRe: sample Pin
    Andareed31-May-03 8:39
    Andareed31-May-03 8:39 
    GeneralRe: sample Pin
    Henk Devos31-May-03 8:44
    Henk Devos31-May-03 8:44 
    GeneralI wanna a entire sample project, too! Pin
    5-Nov-00 14:08
    suss5-Nov-00 14:08 
    GeneralI'm impressed! Pin
    Peter Broughton1-Nov-00 14:17
    sussPeter Broughton1-Nov-00 14:17 
    GeneralGood info, but... Pin
    Nugpot Osamot15-Mar-00 0:15
    sussNugpot Osamot15-Mar-00 0:15 
    GeneralRe: Good info, but... Pin
    28-Jun-01 6:35
    suss28-Jun-01 6:35 
    GeneralExcellent project Pin
    Mr. Art14-Feb-00 19:06
    sussMr. Art14-Feb-00 19:06 
    GeneralPerfect work!!! But I wanna a entire sample project! Pin
    Dandy Cheung17-Jan-00 22:46
    Dandy Cheung17-Jan-00 22:46 

    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.