Click here to Skip to main content
15,434,147 members
Articles / Programming Languages / C++
Posted 21 Jun 2004


118 bookmarked

How to overlay an icon over existing shell objects in 3 easy steps

Rate me:
Please Sign up or sign in to vote.
4.59/5 (24 votes)
30 Jun 20046 min read
How to implement an Icon Overlay identifier.

Image 1


Have 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 object

After you start Visual Studio .NET:

  1. Choose File menu / New Project.
  2. Choose Visual C++ Project / ATL Project.
  3. Name the project "OverlayIcon", and press OK.

Now, in the ATL project wizard:

  1. Choose "Application Settings" tab.
  2. Uncheck "Attributed".
  3. Make sure you selected server type as "Dynamic Link Library".
  4. If you want to have MFC support, check its option (in this article. we won't be needing MFC).
  5. Now press "Finish".

Now, in VC's ClassView or using the "Project" menu:

  1. Right click on the "OverlayIcon" tree root (in class view).
  2. Then choose Add / New Class.
  3. You can achieve (1) and (2) via "Project menu / Add New Class".
  4. Expand the "Visual C++" tree to see the "ATL" node.
  5. Click on "ATL", and choose from the view on the right "ATL Simple Object", and press Open.

Now, in the "ATL Simple Object Wizard" window:

  1. In the "C++ / Short Name" text box, type "MyOverlayIcon".
  2. You will notice that all the other text boxes have been also filled.
  3. Now, press "Finish".

At this stage, you should see in the ClassView a new class named CMyOverlayIcon.

Before moving to step two, which is about implementing an IShellIconOverlayIdentifier interface, you need to add a new icon to your resources. This icon should be transparent all over except a small area of it which will be overlaid on top of existing objects' icons. The provided icon has a small "a" on its lower right corner.

Step 2 - Implementing a Shell Icon Overlay Identifier interface

Now, 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>
  // IShellIconOverlayIdentifier Methods
  STDMETHOD(GetOverlayInfo)(LPWSTR pwszIconFile, 
           int cchMax,int *pIndex,DWORD* pdwFlags);
  STDMETHOD(GetPriority)(int* pPriority);
  STDMETHOD(IsMemberOf)(LPCWSTR pwszPath,DWORD dwAttrib);


  HRESULT FinalConstruct()
    return S_OK;
  void FinalRelease() 

OBJECT_ENTRY_AUTO(__uuidof(MyOverlayIcon), CMyOverlayIcon)

The three methods to implement are:


Provides the location of the icon overlay's bitmap.

This method is first called during initialization, it returns the fully qualified path of the file containing the icon overlay image, and its zero-based index within the file. The icon can be contained in any of the standard file types, including .exe, .dll, and .ico.


Specifies the priority of an icon overlay.

This method is called only during initialization. It assigns a priority value (ranging from 0=Highest to 100=Lowest priority) to the handler's icon overlay.

Priority helps resolve the conflict when multiple handlers are installed.


Specifies whether an icon overlay should be added to a Shell object's icon.

You may return S_OK to allow adding the overlay icon or S_FALSE to keep object's icon intact.

In this example, our IsMemberOf() simply checks if the file contains the string "CodeProject", if so then our icon overlay is applied. You can change this criteria to match your needs.

Now, open MyOverlayIcon.cpp to implement the IShellIconOverlayIdentifier methods.

// 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

  return S_OK;

// IShellIconOverlayIdentifier::GetPriority
// returns the priority of this overlay 0 being the highest. 
STDMETHODIMP CCOverlayProvider::GetPriority(int* pPriority)
  // we want highest priority 
  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);

  // Criteria
  if (wcsstr(s, L"codeproject") != 0)
    r = S_OK;


  return r;

Step 3 - Registering the Interface

In addition to normal COM registration, you must register this icon overlay handler under:


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:

    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}'

    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

I have copied the DLL over a new computer, how can I activate it?

You simply need to register the DLL.

However, make sure you distribute the needed dependencies with your DLL.

I am having error as: "Cannot open DllXYZ.dll for writing", what is wrong?

Since this DLL is loaded by Explorer.exe or other applications that use the SHELL, you need to close all those applications that already created an instance of your DLL.

Check this article which clarifies how to deal with such issues.

Ok, I want to remove the icon overlay, how can I do that?You simply unregister your DLL. For example, try using regsvr32.exe /u myDll.dll.
I am unable to compile the code due to this warning: "error C2787: 'IShellIconOverlayIdentifier' : no GUID has been associated with this object".

To solve this problem, you need to make use of Platform's SDK headers. Do this by:

  • Tools menu / Options.
  • Choose "Projects" node.
  • Click on "VC++ Directories".
  • Select from the "Show directories for" combo box, the "Include files".
  • Click on the list item that has "PlatformSDK\include", and move it up in the list so it has higher include precedence.
  • Click "OK", and try to compile now.
How can I have different overlay icons for different criteria?

AFAIK, you will need to create another COM object implementing IShellIconOverlayIdentifier. However, this new object can reside in the same project.

Perhaps this article can be of use to you.


In 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).


  • 06/20/2004 - Initial version.
  • 07/01/2004 - Article title and screenshots updated.


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
United States United States
Elias (aka lallousx86, @0xeb) has always been interested in the making of things and their inner workings.

His computer interests include system programming, reverse engineering, writing libraries, tutorials and articles.

In his free time, and apart from researching, his favorite reading topics include: dreams, metaphysics, philosophy, psychology and any other human/mystical science.

Former employee of Microsoft and Hex-Rays (the creators of IDA Pro), was responsible about many debugger plugins, IDAPython project ownership and what not.

Elias currently works as an Anticheat engineer in Blizzard Entertainment.

Elias co-authored 2 books and authored one book:

- Practical Reverse Engineering
- The Antivirus Hacker's Handbook
- The Art of Batch Files Programming

Comments and Discussions

Questionthis error is coming,what should I do? Pin
Member 1374680811-Oct-18 23:50
MemberMember 1374680811-Oct-18 23:50 
QuestionNo OverlayIcons on Win10 x64 Pin
Member 125855054-Jul-16 6:04
MemberMember 125855054-Jul-16 6:04 
AnswerRe: No OverlayIcons on Win10 x64 Pin
Member 948707125-Aug-20 3:55
MemberMember 948707125-Aug-20 3:55 
Questionit doesn't work in win7 64bit. Pin
Jeff Cheng5-Apr-15 6:30
MemberJeff Cheng5-Apr-15 6:30 
AnswerRe: it doesn't work in win7 64bit. Pin
Member 24995765-Apr-16 23:43
MemberMember 24995765-Apr-16 23:43 
QuestionChange criteria. Pin
Marocos2-Jan-15 13:55
MemberMarocos2-Jan-15 13:55 
AnswerRe: Change criteria. Pin
Elias Bachaalany30-Jan-15 8:23
MemberElias Bachaalany30-Jan-15 8:23 
GeneralRe: Change criteria. Pin
Marocos6-Feb-15 13:21
MemberMarocos6-Feb-15 13:21 
Questionvery good Pin
caijian_zhang21-Jul-14 0:12
Membercaijian_zhang21-Jul-14 0:12 
Questionthis can't build in vs2010,and i want know how to use it ? Pin
forcj92822-Dec-13 20:40
Memberforcj92822-Dec-13 20:40 
AnswerRe: this can't build in vs2010,and i want know how to use it ? Pin
Marwan Yassin9-Feb-14 1:11
MemberMarwan Yassin9-Feb-14 1:11 
Questiondll isn't registered for x86 in Windows 7 64 bit PinPopular
MadMaksidrom17-Jun-13 21:29
MemberMadMaksidrom17-Jun-13 21:29 
AnswerRe: dll isn't registered for x86 in Windows 7 64 bit Pin
Member 125855054-Jul-16 22:32
MemberMember 125855054-Jul-16 22:32 
Questionrunning the codes Pin
srikrishnathanthri7-May-13 20:57
Membersrikrishnathanthri7-May-13 20:57 
QuestionTo register a module, you must provide a binary name. Pin
Member 800856025-Apr-13 4:50
MemberMember 800856025-Apr-13 4:50 
QuestionWindows7 big and middle icon styles show files and the overlay icon can't show at Right corner Pin
neulsq19-Sep-12 22:24
Memberneulsq19-Sep-12 22:24 
QuestionRe: Windows7 big and middle icon styles show files and the overlay icon can't show at Right corner Pin
Member 27289434-Jan-13 6:04
MemberMember 27289434-Jan-13 6:04 
QuestionDLL works only partially Pin
AdamSharon119-Aug-12 23:24
MemberAdamSharon119-Aug-12 23:24 
AnswerRe: DLL works only partially Pin
chen.yufei25-Feb-13 18:22
Memberchen.yufei25-Feb-13 18:22 
Questionhow can we implement multiple overlay icon during run time decide? Pin
skyramesh9-Apr-12 21:19
Memberskyramesh9-Apr-12 21:19 
QuestionRe: how can we implement multiple overlay icon during run time decide? Pin
skyramesh17-Apr-12 2:37
Memberskyramesh17-Apr-12 2:37 
AnswerRe: how can we implement multiple overlay icon during run time decide? Pin
Member 48490023-May-12 21:57
MemberMember 48490023-May-12 21:57 
GeneralRe: how can we implement multiple overlay icon during run time decide? Pin
doerrst24-Jul-12 23:05
Memberdoerrst24-Jul-12 23:05 
QuestionHow can i debugging? Pin
msrameshkumar30-Mar-12 1:49
Membermsrameshkumar30-Mar-12 1:49 
AnswerRe: How can i debugging? Pin
dr_zlo30-Mar-12 4:44
Memberdr_zlo30-Mar-12 4:44 

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.