Windows provides the function ExtractIconEx to extract icons from a exe or dll by index. It allows you to get a HICON handle to a “small” and a “large” version of the icon. Trouble is.. what are the actual dimensions of the small or large icons. The answer is to use GetSystemMetrics with the flags SM_CXICON, SM_CYICON, SM_CXSMICON, and SM_CYSMICON.
This is great, but unfortunately this function has not been updated for Vista or Windows 7, which use much larger icons and if you want a particular size ExtractIconEx will not work for you. So instead of relying on this function you can write some code that enumerates the resources in the target file yourself. The basic idea is to enumerate the resources and find the icons, then read the icon information to find the one that matches the desired size and format (bit count).
The example below implements this idea, it will find a 32bit icon of the requested size if it exists.
<code> HICON WINAPI ExtractIconAtSize(TCHAR* filePath, UINT nIconIndex, int sz) { //Load the library as a data file HMODULE hLib = LoadLibraryEx(filePath, NULL, LOAD_LIBRARY_AS_DATAFILE); if( !hLib ) return NULL; MyEnumData data; data.nIconIndex = nIconIndex; data.hIcon = NULL; data.sz = sz; //currently only interested in 32bit icons data.bitCount = 32; //find the resource item EnumResourceNames(hLib, RT_GROUP_ICON, (ENUMRESNAMEPROC)&FindGroupIconProc, (LONG)&data); FreeLibrary(hLib); return data.hIcon; } typedef struct { UINT Width, Height, Colors; // Width, Height and bpp LPBYTE lpBits; // ptr to DIB bits DWORD dwNumBytes; // how many bytes? LPBITMAPINFO lpbi; // ptr to header LPBYTE lpXOR; // ptr to XOR image bits LPBYTE lpAND; // ptr to AND image bits } ICONIMAGE, *LPICONIMAGE; #pragma pack( push ) #pragma pack( 2 ) typedef struct { BYTE bWidth; // Width, in pixels, of the image BYTE bHeight; // Height, in pixels, of the image BYTE bColorCount; // Number of colors in image (0 if >=8bpp) BYTE bReserved; // Reserved WORD wPlanes; // Color Planes WORD wBitCount; // Bits per pixel DWORD dwBytesInRes; // how many bytes in this resource? WORD nID; // the ID } GRPICONDIRENTRY, *LPGRPICONDIRENTRY; #pragma pack( pop ) #pragma pack( push ) #pragma pack( 2 ) typedef struct { WORD idReserved; // Reserved (must be 0) WORD idType; // Resource type (1 for icons) WORD idCount; // How many images? GRPICONDIRENTRY idEntries[1]; // The entries for each image } GRPICONDIR, *LPGRPICONDIR; #pragma pack( pop ) struct MyEnumData { UINT nIconIndex; HICON hIcon; int sz; int bitCount; }; BOOL CALLBACK FindGroupIconProc(HANDLE hModule, LPCTSTR lpszType, LPTSTR lpszName, LONG lParam) { MyEnumData *data = (MyEnumData*) lParam; //check if this is the index we want if( data->nIconIndex == 0 ) { HRSRC hRsrc = FindResource((HMODULE)hModule, lpszName, lpszType); HGLOBAL hGroup = LoadResource((HMODULE)hModule, hRsrc); GRPICONDIR * lpGrpIconDir = (LPGRPICONDIR)LockResource( hGroup ); for( int i=0; i < lpGrpIconDir->idCount; ++i ) { //get icon header info GRPICONDIRENTRY * e = &lpGrpIconDir->idEntries[i]; hRsrc = FindResource((HMODULE) hModule, MAKEINTRESOURCE( e->nID ), RT_ICON ); HGLOBAL hGlobal = LoadResource( (HMODULE)hModule, hRsrc ); ICONIMAGE *lpIconImage = (LPICONIMAGE)LockResource( hGlobal ); //check the desired size and bit count if(e->bWidth == data->sz && e->wBitCount == data->bitCount) { data->hIcon = CreateIconFromResourceEx( (PBYTE)lpIconImage, e->dwBytesInRes, TRUE, 0x00030000,//DWORD dwVersion, e->bWidth, e->bHeight, 0 ); return FALSE; } }; return FALSE; } --(data->nIconIndex); return TRUE; } </code>