Click here to Skip to main content
11,435,451 members (62,482 online)
Click here to Skip to main content

Changing default icons for folders and drives

, 26 Jan 2003
Rate this:
Please Sign up or sign in to vote.
Shows how to globally change the icons for folders and drives. Also shows some nifty tricks you might find handy in your applications.

Introduction

This article explains a simple way to get and set icons for folders (open and closed), hard drives, floppies and CD drives. The default icons are stored in Shell32.dll as icon resources. To change the icons, we need to modify the registry by adding some values and to set them back to default icons, we simply remove the values we added. Of course simply changing the registry values won't change the icons because Windows will take the icons from the icon cache. Tweak UI has a feature to flush the icon cache and I ran Spy++ on it as well as monitored registry changes. I found that what they do is to change the icon size value in the WindowMetrics registry key, broadcast a WM_SETTINGCHANGE with SPI_SETNONCLIENTMETRICS, change the icon size  back to it's original value and again broadcast the WM_SETTINGCHANGE  message. I did the same and found that it works fine.

Demo project

I put together a simple demo project for making things clearer for you. It will let you get and set folder and drive icons as well as let you set it back to their default values. I've used some interesting techniques in the program which I'll explain below for the interested ones.

Getting default (or customized) icons

The default icons are stored in Shell32.dll and we simply read the hard coded indexed icons out of the DLL. But before that we first check to see if the icons have already been customized by reading the registry.

void CShellIconChangerDlg::OnCbnSelchangeCombo1()
{
    //First chk if customized

    CString val;
    HKEY hKey;

    LONG result = ::RegOpenKeyEx(HKEY_LOCAL_MACHINE,
        "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Icons",
        0,KEY_READ,&hKey);
    BYTE buff[512];
    ZeroMemory(buff,511);
    DWORD sz = sizeof buff;
    DWORD typ = REG_SZ;
    CString indbuff;
    indbuff.Format("%d",m_combo.GetItemData(m_combo.GetCurSel()));
    result = RegQueryValueEx(hKey,indbuff,0,&typ,buff,&sz);
    RegCloseKey(hKey);

    if(result == ERROR_SUCCESS)
    {
        val = buff;
        int comma = val.ReverseFind(',');
        int cusindex = 0;
        if(comma != -1)
        {
            CString tmpstr = val.Mid(comma+1);
            cusindex = atoi(tmpstr);
            val = val.Left(comma); 
        }

        HICON hIcon = ::ExtractIcon(AfxGetApp()->m_hInstance,
            val,cusindex);
        m_curicon.SetIcon(hIcon);
    }
    else
    {
        char sysfolder[MAX_PATH];
        GetSystemDirectory(sysfolder,MAX_PATH);
        CString strIconPath = sysfolder;
        strIconPath += "\\Shell32.dll";
        HICON hIcon = ::ExtractIcon(AfxGetApp()->m_hInstance,
            strIconPath,m_combo.GetItemData(m_combo.GetCurSel()));
        m_curicon.SetIcon(hIcon);
    }
}

ExtractIcon is a rather unknown function which will extract an indexed icon resource from a DLL or EXE file. Of course I might be wrong as to it's being unknown, I was speaking personally here. I didn't know of such a function till today.

Setting custom icons

void CShellIconChangerDlg::OnBnClickedOk()
{
    HKEY hKey;
    DWORD dwDisposition;
    LONG result = ::RegCreateKeyEx(HKEY_LOCAL_MACHINE,
        "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Icons",0,
        NULL,REG_OPTION_NON_VOLATILE,KEY_WRITE,NULL,&hKey,&dwDisposition);
    CString buff;
    buff.Format("%d",m_combo.GetItemData(m_combo.GetCurSel()));
    RegSetValueEx(hKey,buff,0,REG_SZ,
        (const BYTE*)m_strIconPath.GetBuffer(0),m_strIconPath.GetLength());
    m_strIconPath.ReleaseBuffer();

    RegCloseKey(hKey);

    RefreshIcons();
    OnCbnSelchangeCombo1();
}

Well, there is not anything very much special here and we simply add a new value to the registry key as shown above. I use RegCreateKeyEx instead of RegOpenKeyEx because by default the sub-key Shell Icons does not exist. As you can see I then call RefreshIcons which is the function that duplicates what Tweak UI does. I'll explain it later in this article.

Setting to default

void CShellIconChangerDlg::OnBnClickedButton2()
{
    HKEY hKey;
    DWORD dwDisposition;
    LONG result = ::RegCreateKeyEx(HKEY_LOCAL_MACHINE,
        "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Icons",0,
        NULL,REG_OPTION_NON_VOLATILE,KEY_WRITE,NULL,&hKey,&dwDisposition);
    CString buff;
    buff.Format("%d",m_combo.GetItemData(m_combo.GetCurSel()));
    RegDeleteValue(hKey,buff);
    RegCloseKey(hKey);

    RefreshIcons();
    OnCbnSelchangeCombo1();
}

Setting to default is a simple matter of deleting the values we added to the registry and calling RefreshIcons.

Browse for icons dialog

void CShellIconChangerDlg::OnBnClickedButton1()
{
    WCHAR szIconPath[MAX_PATH]={0};
    int index = 0;
    if(PickIconDlg(m_hWnd,(WCHAR*)&szIconPath,MAX_PATH,&index))
    {
        CString str;
        str.Format("%S,%d",szIconPath,index);
        m_strIconPath = str;
        HICON hIcon = ::ExtractIcon(AfxGetApp()->m_hInstance,
            CString(szIconPath),index);
        m_iconpreview.SetIcon(hIcon);
    }
}

I have used the PickIconDlg shell function to show the user the standard shell browser dialog. It will let you browse icon files as well as DLLs and other files containing icons. It's only available in Shell32.dll version 5.0 and above, which means this is not available for pre-Windows 2000 users.

RefreshIcons similaire à Tweak UI

void CShellIconChangerDlg::RefreshIcons()
{
    CString val;
    HKEY hKey;

    LONG result = ::RegOpenKeyEx(HKEY_CURRENT_USER,
        "Control Panel\\Desktop\\WindowMetrics",
        0,KEY_READ,&hKey);
    BYTE buff[256];
    ZeroMemory(buff,255);
    DWORD sz = sizeof buff;
    DWORD typ = REG_SZ;
    RegQueryValueEx(hKey,"Shell Icon Size",0,&typ,buff,&sz);
    RegCloseKey(hKey);

    val = buff;

    int i = atoi(val);
    i++;
    val.Format("%d",i);

    result = ::RegOpenKeyEx(HKEY_CURRENT_USER,
        "Control Panel\\Desktop\\WindowMetrics",
        0,KEY_WRITE,&hKey);
    RegSetValueEx(hKey,"Shell Icon Size",0,REG_SZ,
        (const BYTE*)val.GetBuffer(0),val.GetLength());
    val.ReleaseBuffer();
    RegCloseKey(hKey);

    ::SendMessage(HWND_BROADCAST ,
        WM_SETTINGCHANGE,SPI_SETNONCLIENTMETRICS,NULL);


    i = atoi(val);
    i--;
    val.Format("%d",i);

    result = ::RegOpenKeyEx(HKEY_CURRENT_USER,
        "Control Panel\\Desktop\\WindowMetrics",
        0,KEY_WRITE,&hKey);
    RegSetValueEx(hKey,"Shell Icon Size",0,REG_SZ,
        (const BYTE*)val.GetBuffer(0),val.GetLength());
    val.ReleaseBuffer();
    RegCloseKey(hKey);

    ::SendMessage(HWND_BROADCAST ,
        WM_SETTINGCHANGE,SPI_SETNONCLIENTMETRICS,NULL);
}

Basically the whole purpose of this function is to flush the icon cache and force Windows to redraw the icons. By changing the shell icon size value in the registry and then broadcasting WM_SETTINGCHANGE with SPI_SETNONCLIENTMETRICS, we manage to flush the icon cache. Of course we then need to set the shell icon size back to  normal. I know it sounds like a rather round about way to do it, but till they add a "ShFlushIconCache" to the shell API, this is the only solution we have.

The index numbers

Icon

Index

Closed folder 3
Open Folder 4
Hard Disk 8
Floppy Disk 6
CDROM Drive 11

Conclusion

Please note that the CDROM index is not valid when you have a CD-RW drive. I haven't figured out the index for CD-RW drives. Or perhaps it did not work in my case because mine is a DVD/CD-RW combo drive. Anyway as usual please send in the feedback through the really cool forum found at the bottom of this article. Thomas Freudenberg has written an article on the same topic here; though in his case, while he does not demonstrate the Tweak UI simulation, he does include a more complete list of icon indices.

License

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

Share

About the Author

Nish Nishant

United States United States
Nish Nishant is a Software Architect/Consultant based out of Columbus, Ohio. He has over 15 years of software industry experience in various roles including Lead Software Architect, Principal Software Engineer, and Product Manager. Nish is a recipient of the annual Microsoft Visual C++ MVP Award since 2002 (13 consecutive awards as of 2014).

Nish is an industry acknowledged expert in the Microsoft technology stack. He authored
C++/CLI in Action for Manning Publications in 2005, and had previously co-authored
Extending MFC Applications with the .NET Framework for Addison Wesley in 2003. In addition, he has over 140 published technology articles on CodeProject.com and another 250+ blog articles on his
WordPress blog. Nish is vastly experienced in team management, mentoring teams, and directing all stages of software development.

Contact Nish : You can reach Nish on his google email id voidnish.

Website and Blog

Comments and Discussions

 
GeneralMy vote of 5 Pin
mustibh23-Oct-10 3:55
membermustibh23-Oct-10 3:55 
GeneralPlacement of all desktop icons are re-arranged Pin
xuxiuxun29-Sep-07 5:27
memberxuxiuxun29-Sep-07 5:27 
GeneralCould not refresh from service on Win2K Pin
namphvn14-Feb-07 19:05
membernamphvn14-Feb-07 19:05 
QuestionApplication format for this? Pin
luciddre4m3-Oct-06 12:50
memberluciddre4m3-Oct-06 12:50 
GeneralWin2k issue Pin
ncalverl29-Jun-06 6:22
memberncalverl29-Jun-06 6:22 
GeneralHelp - urgent !!! Pin
eyal_gu6-Feb-05 23:30
membereyal_gu6-Feb-05 23:30 
Generalno Shell Icon subKey... Pin
Pawel Zarzycki15-Sep-04 2:17
memberPawel Zarzycki15-Sep-04 2:17 
Question"PickIconDlg" Shell function? Pin
liushan22-Jun-04 23:41
memberliushan22-Jun-04 23:41 
QuestionAbout "PickIconDlg" Shell function? Pin
liushan22-Jun-04 23:40
memberliushan22-Jun-04 23:40 
GeneralPer Drive Icon Pin
GLM211-Oct-03 3:35
memberGLM211-Oct-03 3:35 
GeneralLooks nice Pin
Matt Newman28-Jan-03 6:31
memberMatt Newman28-Jan-03 6:31 
GeneralRe: Looks nice Pin
Nishant S28-Jan-03 12:36
editorNishant S28-Jan-03 12:36 
QuestionAre you using VC++ 7.1 ? Pin
Jerry Evans27-Jan-03 8:42
memberJerry Evans27-Jan-03 8:42 
AnswerRe: Are you using VC++ 7.1 ? Pin
Nishant S27-Jan-03 17:19
editorNishant S27-Jan-03 17:19 
AnswerRe: Are you using VC++ 7.1 ? Pin
Thomas Freudenberg27-Jan-03 22:55
memberThomas Freudenberg27-Jan-03 22:55 
GeneralRe: Are you using VC++ 7.1 ? Pin
Nishant S28-Jan-03 5:13
editorNishant S28-Jan-03 5:13 
Generalis it for Win2K? Pin
gok5-Feb-03 15:08
membergok5-Feb-03 15:08 
GeneralGood article Pin
Nick Parker27-Jan-03 6:01
editorNick Parker27-Jan-03 6:01 
GeneralRe: Good article Pin
Nishant S27-Jan-03 17:20
editorNishant S27-Jan-03 17:20 
GeneralSystemParametersInfo Pin
Maximilian Hänel27-Jan-03 1:38
memberMaximilian Hänel27-Jan-03 1:38 
GeneralRe: SystemParametersInfo Pin
Nishant S27-Jan-03 3:59
editorNishant S27-Jan-03 3:59 
GeneralRe: SystemParametersInfo Pin
Nishant S28-Jan-03 12:36
editorNishant S28-Jan-03 12:36 
GeneralRe: SystemParametersInfo Pin
Maximilian Hänel29-Jan-03 0:12
memberMaximilian Hänel29-Jan-03 0:12 
GeneralMore index numbers Pin
Thomas Freudenberg27-Jan-03 0:10
memberThomas Freudenberg27-Jan-03 0:10 
GeneralRe: More index numbers Pin
Nishant S27-Jan-03 3:57
editorNishant S27-Jan-03 3:57 
GeneralRe: More index numbers Pin
Thomas Freudenberg27-Jan-03 4:03
memberThomas Freudenberg27-Jan-03 4:03 
GeneralRe: More index numbers Pin
Nishant S27-Jan-03 4:35
editorNishant S27-Jan-03 4:35 
GeneralRe: More index numbers Pin
Thomas Freudenberg27-Jan-03 5:13
memberThomas Freudenberg27-Jan-03 5:13 
GeneralRe: More index numbers Pin
Nishant S27-Jan-03 17:22
editorNishant S27-Jan-03 17:22 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Terms of Use | Mobile
Web04 | 2.8.150428.2 | Last Updated 27 Jan 2003
Article Copyright 2003 by Nish Nishant
Everything else Copyright © CodeProject, 1999-2015
Layout: fixed | fluid