Click here to Skip to main content
Click here to Skip to main content
Add your own
alternative version

Retrieving shell icons

, 19 Jun 2002 CPOL
Get shell icons, even if they're customized
shellicon_demo.zip
ShellIconDemo.dsp
ShellIconDemo.dsw
res
ShellIconDemo.ico
ShellIconDemo.manifest
shellicon_exe.zip
ShellIconDemo.exe
shellicon_src.zip
#include "stdafx.h"
#include "ShellIcons.h"

#ifndef _AFXDLL

#include <vector>
#include <string>

namespace std
{
#ifdef _UNICODE
	typedef wstring tstring;
#else
	typedef string tstring;
#endif
}

namespace {

/**
*	Yet another tokenizer
*
*	\param	x			Output iterator
*	\param	in			The string to tokenize
*	\param	delimiters	A string containing token separators
*
*	\par Original take from
*	"http://gcc.gnu.org/onlinedocs/libstdc++/21_strings/stringtok_std_h.txt"
*
*	The Standard C (and C++) function strtok() leaves a lot to be desired in terms of user-friendliness.
*	It's unintuitive, it destroys the character string on which it operates, and it requires you to handle
*	all the memory problems. But it does let the client code decide what to use to break the string into
*	pieces; it allows you to choose the "whitespace," so to speak. 
*
*	A C++ implementation lets us keep the good things and fix those annoyances. The implementation here is
*	more intuitive (you only call it once, not in a loop with varying argument), it does not affect the
*	original string at all, and all the memory allocation is handled for you. 
*
*	It's called tokenize, and it's a template function. It's given in this file in a less-portable for
*	than it could be, to keep this example simple (for example, see the comments on what kind of string it
*	will accept). The author uses a more general (but less readable) form of it for parsing command
*	strings and the like. If you compiled and ran this code using it: 
*	\code
   std::list<std::string>  ls;
   utl::tokenize (std::back_inserter(ls), " this  \t is\t\n  a test  ");
   for (std::list<std::string>::const_iterator it = ls.begin(); it != ls.end(); ++it)
   {
       std::cerr << ':' << (*it) << ":\n";
   }
	\endcode
*	You would see this as output: 
*	<pre>
   :this:
   :is:
   :a:
   :test:
</pre>
*	with all the whitespace removed. The original \a s is still available for use, \a ls will clean up
*	after itself, and \a ls.size() will return how many tokens there were. 
*/
	template <typename outit>
	void tokenize (outit x, const std::tstring &in, const TCHAR * delimiters = _T(" \t\n"))
	{
		const std::tstring::size_type len = in.length();
		std::tstring::size_type i = 0;

		while ( i < len )
		{
			// eat leading whitespace
			i = in.find_first_not_of (delimiters, i);
			if (i == std::tstring::npos)
				return;   // nothing left but white space

			// find the end of the token
			std::tstring::size_type j = in.find_first_of (delimiters, i);

			// push token
			if (j == std::tstring::npos) {
				*x = in.substr(i);
				++x;
				return;
			} else {
				*x = in.substr(i, j-i);
				++x;
			}

			// set up for next loop
			i = j + 1;
		}
	}
} // anonymous namespace

#endif // _AFXDLL

HICON ExtractShellIcon (int nIndex, bool bLargeIcons /*= false*/)
{
	HICON hIcon = NULL;

	// Shell icons can be customized by the registry:
	// HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Shell Icons
	// "<ShellIconIndex>" = "<Filename>,<IconIndex>"
	// E.g.
	// "3" = "c:\MyFolderIcon.ico,1"
	HKEY hkeyShellIcons;
	if (RegOpenKeyEx (HKEY_LOCAL_MACHINE, _T("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Icons"), 0, KEY_READ, &hkeyShellIcons) == ERROR_SUCCESS)
	{
		TCHAR szBuffer[ MAX_PATH * sizeof TCHAR];
		DWORD dwSize = MAX_PATH * sizeof TCHAR;

		TCHAR szIndex[6] = {0};
		_stprintf (szIndex, _T("%d"), nIndex);
		if (RegQueryValueEx (hkeyShellIcons, szIndex, NULL, NULL, (LPBYTE)szBuffer, &dwSize) == ERROR_SUCCESS)
		{
#ifdef _AFXDLL
			CString strFileName, strIndex;
			VERIFY (AfxExtractSubString (strFileName, szBuffer, 0, _T(',')));
			VERIFY (AfxExtractSubString (strIndex, szBuffer, 1, _T(',')));
			ExtractIconEx (strFileName, atoi(strIndex), bLargeIcons ? &hIcon : NULL, bLargeIcons ? NULL : &hIcon, 1);
#else
			std::vector<std::tstring> ls;
			tokenize (std::back_inserter(ls), szBuffer, _T(","));
			ExtractIconEx (ls[0].c_str(), atoi(ls[1].c_str()), bLargeIcons ? &hIcon : NULL, bLargeIcons ? NULL : &hIcon, 1);
#endif
		}

		RegCloseKey( hkeyShellIcons );
	}

	// Not customized? Then get the original icon from shell23.dll
	if (!hIcon)
		ExtractIconEx (_T("SHELL32.DLL"), nIndex, bLargeIcons ? &hIcon : NULL, bLargeIcons ? NULL : &hIcon, 1);

	return hIcon;
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

Thomas Freudenberg
Architect Pharmatechnik GmbH & Co. KG
Germany Germany
No Biography provided
Follow on   Twitter   Google+   LinkedIn

| Advertise | Privacy | Terms of Use | Mobile
Web04 | 2.8.141223.1 | Last Updated 20 Jun 2002
Article Copyright 2002 by Thomas Freudenberg
Everything else Copyright © CodeProject, 1999-2014
Layout: fixed | fluid