|
|||||||||||||||||||||||||||||||||||||||||||
|
|||||||||||||||||||||||||||||||||||||||||||
|
Announcements
Chapters
Services
Feature Zones
|
IntroductionHave you ever wondered how to draw/overlay small icons over existing icons? Or how to have some files displayed with an altered icon to denote a specific state? Or even wondered how shortcuts are displayed with small arrows over your application's icon? I had these questions in mind, but after some research, I found that this can be easily achieved via "Shell Icon Overlay Identifier" In short, icon overlays are usually small icons placed over an existing icon of a shell object in Windows's Explorer or Desktop. A widely known example is the shortcut arrow icon that is overlaid over existing objects' icons. A shell object can be a physical file, a namespace, a shortcut, .... In this article, you will learn how to implement a shell icon overlay identifier in a very easy way. No prior knowledge about shell extensions or shell programming is required. However, to get basic knowledge about shell programming, please check this article's references. It is preferable that you have Visual Studio .NET and the Platform SDK, because the steps described in this article are for VS.NET, they might work for you if you use VS 6.0. For your convenience, there is a comprehensive Q&A section at the end of the article. Step 1 - Creating a simple COM objectAfter you start Visual Studio .NET:
Now, in the ATL project wizard:
Now, in VC's ClassView or using the "Project" menu:
Now, in the "ATL Simple Object Wizard" window:
At this stage, you should see in the ClassView a new class named Before moving to step two, which is about implementing an Step 2 - Implementing a Shell Icon Overlay Identifier interfaceNow, open MyOverlayIcon.h, and adjust / add entries as indicated, in bold, below: // MyOverlayIcon.h : Declaration of the CMyOverlayIcon #pragma once #include "resource.h" // main symbols #include "OverlayIcon.h" // You can put these includes in "stdafx.h" if you want #include <shlobj.h> #include <comdef.h> // CMyOverlayIcon class ATL_NO_VTABLE CMyOverlayIcon : public CComObjectRootEx<CComSingleThreadModel>, public CComCoClass<CMyOverlayIcon, &CLSID_MyOverlayIcon>, public IShellIconOverlayIdentifier, public IDispatchImpl<IMyOverlayIcon, &IID_IMyOverlayIcon, &LIBID_OverlayIconLib, /*wMajor =*/ 1, /*wMinor =*/ 0> { public: CMyOverlayIcon() { } // IShellIconOverlayIdentifier Methods STDMETHOD(GetOverlayInfo)(LPWSTR pwszIconFile, int cchMax,int *pIndex,DWORD* pdwFlags); STDMETHOD(GetPriority)(int* pPriority); STDMETHOD(IsMemberOf)(LPCWSTR pwszPath,DWORD dwAttrib); DECLARE_REGISTRY_RESOURCEID(IDR_MYOVERLAYICON) BEGIN_COM_MAP(CMyOverlayIcon) COM_INTERFACE_ENTRY(IMyOverlayIcon) COM_INTERFACE_ENTRY(IDispatch) COM_INTERFACE_ENTRY(IShellIconOverlayIdentifier) END_COM_MAP() DECLARE_PROTECT_FINAL_CONSTRUCT() HRESULT FinalConstruct() { return S_OK; } void FinalRelease() { } public: }; OBJECT_ENTRY_AUTO(__uuidof(MyOverlayIcon), CMyOverlayIcon) The three methods to implement are:
In this example, our Now, open MyOverlayIcon.cpp to implement the // MyOverlayIcon.cpp : Implementation of CMyOverlayIcon #include "stdafx.h" #include "MyOverlayIcon.h" // CMyOverlayIcon // IShellIconOverlayIdentifier::GetOverlayInfo // returns The Overlay Icon Location to the system STDMETHODIMP CCOverlayProvider::GetOverlayInfo( LPWSTR pwszIconFile, int cchMax, int* pIndex, DWORD* pdwFlags) { // Get our module's full path GetModuleFileNameW(_AtlBaseModule.GetModuleInstance(), pwszIconFile, cchMax); // Use first icon in the resource *pIndex=0; *pdwFlags = ISIOI_ICONFILE | ISIOI_ICONINDEX; return S_OK; } // IShellIconOverlayIdentifier::GetPriority // returns the priority of this overlay 0 being the highest. STDMETHODIMP CCOverlayProvider::GetPriority(int* pPriority) { // we want highest priority *pPriority=0; return S_OK; } // IShellIconOverlayIdentifier::IsMemberOf // Returns whether the object should have this overlay or not STDMETHODIMP CCOverlayProvider::IsMemberOf(LPCWSTR pwszPath, DWORD dwAttrib) { wchar_t *s = _wcsdup(pwszPath); HRESULT r = S_FALSE; _wcslwr(s); // Criteria if (wcsstr(s, L"codeproject") != 0) r = S_OK; free(s); return r; } Step 3 - Registering the InterfaceIn addition to normal COM registration, you must register this icon overlay handler under: HKEY_LOCAL_MACHINE\Software\Microsoft\Windows
\CurrentVersion\Explorer\ShellIconOverlayIdentifiers
There, you create a new subkey (named for example MyOverlayIcon) and set its default value to the string form of the object's class identifier (CLSID) globally unique identifier (GUID). Another way of performing this is to use the project's appropriate *.RGS file which will handle the registration / unregistration automatically. In order to achieve this, please open MyOverlayIcon.rgs and add the following lines in bold: HKCR
{
OverlayIcon.MyOverlayIcon.1 = s 'MyOverlayIcon Class'
{
CLSID = s '{81539FE6-33C7-4CE7-90C7-1C7B8F2F2D40}'
}
OverlayIcon.MyOverlayIcon = s 'MyOverlayIcon Class'
{
CLSID = s '{81539FE6-33C7-4CE7-90C7-1C7B8F2F2D40}'
CurVer = s 'OverlayIcon.MyOverlayIcon.1'
}
NoRemove CLSID
{
ForceRemove {81539FE6-33C7-4CE7-90C7-1C7B8F2F2D40} = s 'MyOverlayIcon Class'
{
ProgID = s 'OverlayIcon.MyOverlayIcon.1'
VersionIndependentProgID = s 'OverlayIcon.MyOverlayIcon'
ForceRemove 'Programmable'
InprocServer32 = s '%MODULE%'
{
val ThreadingModel = s 'Apartment'
}
val AppID = s '%APPID%'
'TypeLib' = s '{ADF1FA2A-6EAA-4A97-A55F-3C8B92843EF5}'
}
}
}
HKLM
{
NoRemove SOFTWARE
{
NoRemove Microsoft
{
NoRemove Windows
{
NoRemove CurrentVersion
{
NoRemove Explorer
{
NoRemove ShellIconOverlayIdentifiers
{
ForceRemove MyOverlayIcon = s '{81539FE6-33C7-4CE7-90C7-1C7B8F2F2D40}'
{
}
}
}
}
}
}
}
}
Notice that we added a complete block that starts from HKLM (HKEY_LOCAL_MACHINE) and ends by adding a new subkey called "MyOverlayIcon" with a default value of the GUID of our object. If you create a new project, you will certainly have a new GUID, use that GUID instead of the one provided in the article. Save the RGS file, compile the project (which, also, will automatically perform registration), and see how the icons are now modified! Q & A
ReferenceIn addition to the reference below, I would like to say thanks to my friend and colleague at work for his help (you know who you are).
History
|
||||||||||||||||||||||||||||||||||||||||||