Creating Icon Handlers
A file class often has a custom icon associated with it, to make its members easily recognizable in Microsoft Windows Explorer. The simplest way to assign a custom icon to a file class is to register the icon's file. However, an icon registered in this way will be the same for all members of the file class. You can have much more flexibility in assigning icons to the members of the file class by implementing an icon handler.
An icon handler is a type of Shell extension handler that allows you to dynamically assign icons to the members of a file class. Every time a file from the class is displayed, the Shell queries the handler for the appropriate icon. For instance, an icon handler can assign different icons to different members of the class, or vary the icon based on the current state of the file.
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 icon handlers.
- Registering Icon Handlers
- Implementing Icon Handlers
Registering Icon Handlers
When you statically register an icon for a file class, you create a DefaultIcon subkey under the ProgID for the file class. Its default value is set to the file that contains the icon. To register an icon handler, you must still have the DefaultIcon subkey, but its default value must be set to "%1". Add an IconHandler subkey to the Shellex subkey of the ProgID subkey, and set its default value to the string form of the handler's class identifier (CLSID) GUID. For a general discussion of how to register Shell extension handlers, see Creating Shell Extension Handlers.
The following example modifies the registry entry from Customizing Icons so that the .myp file class now uses a shortcut menu handler instead of a statically defined icon.
(Default) = MyProgram Application
Implementing Icon Handlers
Like all Shell extension handlers, icon handlers are in-process Component Object Model (COM) objects implemented as DLLs. They must export two interfaces in addition to IUnknown: IPersistFile and IExtractIcon.
The Shell initializes the handler through its IPersistFile interface. It uses this interface to request the handler's CLSID and provides it with the file's name. The rest of the operation takes place through the IExtractIcon interface. For a general discussion of how to implement Shell extension handlers, including the IPersistFile interface, see Creating Shell Extension Handlers. The remainder of this document discusses how to implement the IExtractIcon interface.
Implementing the IExtractIcon Interface
Icons are identified by their location in the file system. The GetIconLocation method is called to request this information. Set the szIconFile parameter to the file name. If there is more than one icon in the file, set piIndex to the icon's index. Assign appropriate values to the two flag variables. If you do not want to specify a file name, or if you do not want the Shell to extract the icon, set the
GIL_NOTFILENAME flag in the pwFlags parameter. You do not need to assign a value to szIconFile, but the handler must provide icon handles when the Shell calls Extract.
If you return a file name, the Shell normally attempts to load the icon from its cache. To prevent the loading of a cached icon, set the
GIL_DONTCACHE flag in the pwFlags parameter. If a cached icon is not loaded, the Shell then calls Extract to request the icon handle.
If a file and index were specified by GetIconLocation, they are passed to Extract in the pszFile and nIconIndex parameters, respectively. If a file name is provided, your handler can return S_FALSE to have the Shell extract the icon. Otherwise, your handler must extract or otherwise produce large and small icons, and assign their HICON handles to the phiconLarge and phiconSmall parameters. The Shell adds the icons to its cache to expedite subsequent calls to the handler.