Creating Property Sheet Handlers

When a user right-clicks a Shell object, the shortcut menu that is displayed normally includes a Properties item. Selecting that item launches a property sheet that allows the user to view, and in some cases modify, the object's properties. You can customize this property sheet by implementing and registering a property sheet handler.

The general procedures for implementing and registering a Shell extension handler are discussed in Creating Shell Extension Handlers. This document focuses on those aspects of implementation that are specific to property sheet handlers.

  • How Property Sheet Handlers Work
  • Registering and Implementing a Property Sheet Handler for a File Class
  • Registering and Implementing a Property Sheet Handler for a Mounted Drive
  • Registering and Implementing a Property Sheet Handler for a Control Panel Application

How Property Sheet Handlers Work

The following illustration shows the Properties property sheet for a Microsoft Windows XP text file.

Property Sheet

This illustration shows the default Properties property sheet that is displayed for any file. For many such property sheets, you can add one or more pages to the property sheet by implementing and registering a property sheet handler.

Property sheet handlers are most commonly registered for a file class. Each handler can add one custom page to the Properties property sheet for the class. These pages typically give users access to properties that are specific to the particular file class. A class consisting of text documents could, for instance, display a page that listed the title and author, and an abstract of the document. A special case of this type of property sheet handler is used to add a page to the Properties property sheet for a mounted drive.

The other use for property sheet handlers is to replace pages in the property sheets displayed by Control Panel applications. A mouse manufacturer, for instance, can use a property sheet handler to replace the Buttons page on the Control Panel's Mouse Properties property sheet with a page that is customized for the characteristics of its mouse.

Like all Shell extension handlers, property sheet handlers are in-process Component Object Model (COM) objects implemented as DLLs. They must export two interfaces in addition to IUnknown: IShellExtInit and IShellPropSheetExt.

The IShellExtInit interface is used by the Shell to initialize the handler. When the Shell calls Initialize, it passes in a data object with the object's name, and the pointer to an item identifier list (PIDL) of the folder that contains the file. The hRegKey parameter is not used with property sheet handlers. The Initialize method must extract the file name from the data object, and store the name and the folder's PIDL for later use. For further details, see the Implementing IShellExtInit section of Creating Shell Extension Handlers.

The remainder of the operation takes place through the handler's IShellPropSheetExt interface. If the property sheet is associated with a file class, the Shell calls AddPages to allow the handler to add a page to the property sheet. If the property sheet is associated with a Control Panel application, the Shell calls ReplacePage to allow the handler to replace a page.

Registering and Implementing a Property Sheet Handler for a File Class

When the user right-clicks a member of a file class to display the Properties property sheet, the Shell calls the property sheet handlers that are registered for the file class. Each handler can add one custom page to the default property sheet.

Registering a Property Sheet Handler for a File Class

In addition to normal COM registration, add a PropertySheetHandlers subkey to the shellex subkey of the ProgID key of the application associated with the file class. Create a subkey of PropertySheetHandlers with the handler's name, and set the default value to the string form of the property sheet handler's class identifier (CLSID) GUID.

To add more than one page to the property sheet, register a handler for each page. The maximum number of pages that a property sheet can support is 32. To register multiple handlers, create a key under the shellex key for each handler, with the default value set to the handler's CLSID GUID. It is not necessary to create a distinct object for each handler, so multiple handlers can all have the same GUID value. The pages will be displayed in the order that their keys are listed under shellex .

The following example illustrates a registry entry that enables two property sheet extension handlers for an example .myp file class. In this example, a separate object is used for each page, but a single object could also be used for both.

HKEY_CLASSES_ROOT

  • .myp

CLSID

{Page 1 Property Sheet Handler CLSID GUID}

  • InProcServer32

{Page 2 Property Sheet Handler CLSID GUID}

  • InProcServer32

MyProgram.1

(Default) = MyProgram Application

shellex

PropertySheetHandlers

  • MyPropSheet1
  • MyPropSheet2

For a general discussion of how to register Shell extension handlers, see Creating Shell Extension Handlers.

Implementing a Property Sheet Handler for a File Class

In addition to the general implementation discussed in How Property Sheet Handlers Work, a property sheet handler for a file class must also have an appropriate implementation of IShellPropSheetExt. Only the AddPages method needs a nontoken implementation. The Shell doesn't call ReplacePage.

Implementing the AddPages Method

The AddPages method allows a property sheet handler to add a page to a property sheet. The method has two input parameters. The first, lpfnAddPage, is a pointer to an AddPropSheetPageProc callback function that is used to provide the Shell with the information needed to add the page to the property sheet. The second, lParam, is a Shell-defined value that is not processed by the handler. It is simply passed back to the Shell when the callback function is called.

The general procedure for implementing AddPages is:

  1. Assign appropriate values to the members of a PROPSHEETPAGE structure. In particular:
    • Assign the variable that holds the handler's reference count to the pcRefParent member. This practice prevents the handler object from being unloaded while the property sheet is still being displayed.
    • You can also implement a PropSheetPageProc callback function and assign its pointer to a pfnCallback member. This function is called when the page is created and when it is about to be destroyed.
  2. Create the page's HPAGE handle by passing the PROPSHEETPAGE structure to CreatePropertySheetPage.
  3. Call the function pointed to by lpfnAddPage. Set its first parameter to the HPAGE handle created in the previous step. Set its second parameter to the lParam value passed in to AddPages by the Shell.
  4. Any messages associated with the page will be passed to the dialog box procedure that was assigned to the pfnDlgProc member of the PROPSHEETPAGE structure.
  5. If you assigned a PropSheetPageProc callback function to pfnCallback, it will be called when the page is about to be destroyed. Your handler can then perform any needed cleanup operations, such as releasing any references it holds.

The following code sample illustrates a simple AddPages implementation.

STDMETHODIMP CShellPropSheetExt::AddPages(LPFNADDPROPSHEETPAGE, lpfnAddPage, LPARAM lParam)
{
    PROPSHEETPAGE  psp;
    HPROPSHEETPAGE hPage;

    psp.dwSize        = sizeof(psp);
    psp.dwFlags       = PSP_USEREFPARENT | PSP_USETITLE | PSP_USECALLBACK;
    psp.hInstance     = g_hInst;
    psp.pszTemplate   = MAKEINTRESOURCE(IDD_PAGEDLG);
    psp.hIcon         = 0;
    psp.pszTitle      = TEXT("Extension Page");
    psp.pfnDlgProc    = (DLGPROC)PageDlgProc;
    psp.pcRefParent   = &g_DllRefCount;
    psp.pfnCallback   = PageCallbackProc;
    psp.lParam        = (LPARAM)this;

    hPage = CreatePropertySheetPage(&psp);
            
    if(hPage) 
    {
        if(lpfnAddPage(hPage, lParam))
        {
            this->AddRef();
            return S_OK;
        }
        else
        {
            DestroyPropertySheetPage(hPage);
        }
    }
    else
    {
        return E_OUTOFMEMORY;
    }
    return E_FAIL;
}

The g_hInst variable is the instance handle to the DLL, and IDD_PAGEDLG is the resource ID of the page's dialog box template. The PageDlgProc function is the dialog box procedure that handles the page's messages. The g_DllRefCount variable holds the object's reference count. The AddPages method calls AddRef to increment it. However, the reference count is released by the callback function, PageCallbackProc, when the page is about to be destroyed.

Registering and Implementing a Property Sheet Handler for a Mounted Drive

Each mounted drive has a Properties sheet that can be displayed by the user. The following illustration shows a Properties property sheet for a CD-ROM drive.

CD-ROM Properties property sheet

There are a wide variety of devices that can be mounted as drives. Because the default property sheet, designed for disk drives, might not be sufficient for some devices, a property sheet handler can be implemented to add a page that is specific to the mounted device. The basic implementation of this type of property sheet handler is identical to that discussed in Registering and Implementing a Property Sheet Handler for a File Class, with two exceptions.

  • The data object passed to the handler's Initialize method may contain the drive path in the CFSTR_MOUNTEDVOLUME format instead of the CF_HDROP format. The CF_HDROP format is used when the device is mounted to a drive letter. The CFSTR_MOUNTEDVOLUME format is used with NTFS file systems when the remote device is mounted to a folder rather than to a drive letter.
  • The handler's GUID is registered under the HKEY_CLASSES_ROOT\Drive\shellex\PropertySheetHandlers key.

Registering and Implementing a Property Sheet Handler for a Control Panel Application

Many Control Panel applications display a Properties property sheet to enable users to view and modify various device and system settings. Two of them—Mouse and Display—allow property sheet handlers to replace one or more of their pages with a custom page. Keyboard previously allowed property sheet handlers to replace the Speed page, but that page is not replaceable in Windows 2000 or Windows XP. The following illustration shows the Mouse Properties property sheet.

Mouse Properties property sheet

Property sheet handlers for Control Panel applications are similar to those for file classes, with three primary exceptions:

  • They are called by a Control Panel application, not the Shell.
  • They are registered differently.

Registering a Property Sheet Handler for a Control Panel Application

A Control Panel application property sheet handler must be registered under Control Panel subkey. This key can be in either of two locations, depending on whether the handler is to be per-user or per-computer. For per-user registration, the Control Panel subkey is HKEY_CURRENT_USER\Control Panel . The macro REGSTR_PATH_CONTROLPANEL as defined in Regstr.h can be used in code in place of "Control Panel". For per-computer registration, the location is

HKEY_LOCAL_MACHINE

Software

Microsoft

Windows

Current Version

  • Controls Folder

This path can be referred to in code as HKEY_LOCAL_MACHINE\REGSTR_PATH_CONTROLSFOLDER, using the REGSTR_PATH_CONTROLSFOLDER macro defined in Regstr.h.

The Control Panel applications that allow property sheet handlers to replace pages have a subkey under the Control Panel's subkey, named for the application such as Mouse and Display. The application's subkey must have a shellex subkey with a PropertySheetHandlers subkey. To register a property sheet handler, add its GUID to the PropertySheetHandlers subkey associated with the Control Panel application. To do so, create a subkey of the PropertySheetHandlers subkey, named for the property sheet handler, and set its default value to the string form of the handler's GUID.

The following example registers a property sheet handler for the Mouse Control Panel application on a per-computer basis. To register it on a per-user basis, replace HKEY_LOCAL_MACHINE\REGSTR_PATH_CONTROLSFOLDER with HKEY_CURRENT_USER\REGSTR_PATH_CONTROLPANEL .

HKEY_LOCAL_MACHINE

REGSTR_PATH_CONTROLSFOLDER

Mouse

shellex

PropertySheetHandlers

  • MyPropHandler

Implementing a Property Sheet Handler for a Control Panel Application

The procedure for implementing a Control Panel property sheet handler is very similar to that discussed in Registering and Implementing a Property Sheet Handler for a File Class. The primary difference is that now ReplacePage needs a nontoken implementation instead of AddPages.

When a Control Panel application is about to display its property sheet, it calls the property sheet handler's ReplacePage method once for each page that can be replaced. The uPageID parameter is set to the page's ID. The IDs for the available pages are defined in Cplext.h. The currently available IDs are listed in the following table.

Page ID Description Control Panel application
CPLPAGE_MOUSE_BUTTONS The Buttons page Mouse
CPLPAGE_MOUSE_PTRMOTION The Motion page Mouse
CPLPAGE_MOUSE_WHEEL The Wheel page Mouse
CPLPAGE_KEYBOARD_SPEED The Speed page Keyboard
CPLPAGE_DISPLAY_BACKGROUND The Background page Display

Otherwise, the procedure for creating and replacing a page is identical to that for adding a page. For further information, see Registering and Implementing a Property Sheet Handler for a File Class.