|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Announcements
Chapters
Services
Feature Zones
|
Note: This is an unedited contribution. If this article is inappropriate,
needs attention or copies someone else's work without reference then please
Report This Article
IntroductionThere are two ways to change a folder icon in Windows:
But what if you want to use different icons for a subset of folders ? Why would you want to ? Consider the following situations:
In all the above examples the ability to select an icon for parts of the folder structure can be a real benefit. Unfortunately there is no easy way in Windows to do this (you could of course change the icon manually for each folder !). Multi-Folder Icons (MFI) lets you do this easily - the image above shows it in operation with several distinct groups of folders shown using different icons. Many File Open dialogs are implemented using an Explorer view so you also get the benefit of the custom icons when opening and saving files:
BackgroundMFI is an Icon Overlay Handler (IOH). Here is a brief extract from the Microsoft documentation about these components:
The basics of implementing an IOH are described in various places - here for example. This article assumes familiarity with the basic concepts involved. As noted above the intention is that an IOH provides the shell with "small images" to overlay on certain Shell objects. However there is nothing to prevent us using a 'full-sized' icon. Thus we can return an icon that completely overlays the normal folder icon with an image of our choosing.
It is easy enough to develop an IOH which checks each file path passed to the Multiple IconsThings get more complicated when we want to have a different icon for folders on the Z: drive and folders on the Y: drive, for instance. Unfortunately, Explorer only allows one icon for each IOH and this is requested when the IOH is initialized. There is no way for a single instance of an IOH to use different icons for different sets of folders. The solution is to register multiple IOHs - one for each set of folders you want to match. Of course each IOH can be an instance of the same component which configures itself when Explorer creates it (based on some information stored in the registry). If you want another set of folders to be displayed with a different icon you only have to add another configuration entry to the registry - this is what MFI does. The next two sections describe the implementation and the configuration required to use the component. ImplementationWe need to provide multiple IOH components in the same dll. The obvious way to implement several near identical classes would be to provide a template class to handle the common functionality, e.g. ////////////////////////////////////////////////////////// // CMFI_IconImpl - Template class for common functionality template <CLASS _T,const CLSID* _pCLSID,UINT _RES, UINT _ICONINDEX> class ATL_NO_VTABLE CMFU_IconImpl : public CComObjectRootEx<CCOMSINGLETHREADMODEL>, public CComCoClass<_T,_pCLSID>, public IShellIconOverlayIdentifier { public: CMFI_IconImpl() { } DECLARE_MY_REGISTRY_RESOURCEID(_RES) DECLARE_NOT_AGGREGATABLE(_T) DECLARE_PROTECT_FINAL_CONSTRUCT() BEGIN_COM_MAP(_T) COM_INTERFACE_ENTRY(IShellIconOverlayIdentifier) END_COM_MAP() public: // IShellIconOverlayIdentifier Methods STDMETHOD(GetOverlayInfo)(LPWSTR pwszIconFile,int cchMax,int* pIndex,DWORD* pdwFlags); STDMETHOD(GetPriority)(int* pIPriority); STDMETHOD(IsMemberOf)(LPCWSTR pwszPath, DWORD dwAttrib); }; Specialised versions derived from this class can then be used to implement the specifics for each component, passing the CLSID as a template parameter. This approach has the benefit of reducing the amount of code you need to write (in fact I use it in another dll which implements a number of IOH components which identify files which are ReadOnly, Unicode or "Loaded-in-memory" - If you are interested these will soon be available here. Unfortunately, this would still not solve the problem of being able to dynamically create instances of the IOH for each folder class - we would have to rebuild the dll each time we needed to add a new one.
What is needed is a component which can initialize itself based on some piece of
configuration information - the CLSID is the outstanding candidate for this. For
each IOH the CLSID will be passed to In the implementation of MFI, both the class factory object and the IOH component implement this interface: interface IMFI_Control : IUnknown { [id(1)] HRESULT Configure(REFCLSID refclsid); }; which does the necessary lookup of parameters based on CLSID.
The only thing left to do is to make sure our initialization code is called so that
we can add the necessary entries under Configuration & Settings
The MFI
Configurator utility can be used to manage all the MFI settings. The settings
are described fully in the help text supplied with this application. The following
summary is for information only.
Explorer opens the following registry key when it starts:
Each subkey found is treated as an Icon Overlay Handler component and the default value of the key is the CLSID of the component in question. MFI dynamically creates entries under this key for each folder mapping that you want. It also creates the registry entries that COM requires to locate the component. The configuration is held in the registry and looks like this:
Where the set of values for each key looks like this:
The entries have the following meaning:
Network DrivesThere is one more configuration parameter which MFI handles - IgnorePaths. This is a REG_SZ value of partial paths delimited by ";". Each path is matched against the start of the target path. If it matches then MFI ignores it - this can be useful for network drives which may not always be switched on. Note - it is a good idea to put the "A:" (or other floppy drive) in this list as MFI wastes about a second at startup trying to access this drive. The delay only happens when Explorer is started for the first time. Comments & Outstanding Issues
About Keith SkillingI am an independent software contractor based in the UK. I am currently working for SwissRe in London. I am also the author of a fantastic utility called CMU - trust me you'll love it as well ! History05/07/07 Links to Configurator added. 04/05/07 First posted to CodeProject.
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||