13

I'm trying to get a high resolution icon or thumbnail in Windows given a full path to that file. Doesn't need to be a thumbnail — a good looking Icon will be great. I Don't care if it's an HICON or an HBITMAP: I'm going to put it in a GDI+ object and render it into a device context.

I've tried using SHGetFileInfo (with various variations on flags), but never get more than a ~32x32 icon back, which scales horribly to the 128 pixels or so that I need.

if (!SHGetFileInfoW(path, 0, &fi, sizeof(fi),
                    SHGFI_ICON | SHGFI_ICONLARGE | SHGFI_TYPENAME))
    return GetLastError();

// fi.hIcon is a valid icon here, but it's horrible quality with
// a black mask on it. I want higher quality, and dare I dream of
// alpha channel? Mask is acceptable, i suppose.

SHGetFileInfo returns "" when I call with SHGFI_ICONLOCATION (which appears to be a known problem with that API).

I've also tried using SHCreateItemFromParsingName name with the intention of getting IThumbnailProvider, but BindToHandler always returns E_NOTIMPL for BHID_ThumbnailHandler ...

IShellItem *psi;
hr = SHCreateItemFromParsingName(path, NULL, IID_PPV_ARGS(&psi));
if (SUCCEEDED(hr))
{
    IThumbnailProvider *pThumbProvider;
    hr = psi->BindToHandler(NULL, BHID_ThumbnailHandler,
                            IID_PPV_ARGS(&pThumbProvider));
    if (SUCCEEDED(hr))
    { 
    // never get here because hr == E_NOTIMPL !!!

I've actually run the Microsoft Thumbnail Providers Sample and found that it suffers from the same problem with BindToInterface.

So, any suggestions on what else I could try? I just want something picture-y that more or less represents this file at, say, at least 100px size — just anything better than 32x32 ...

MarcWan
  • 2,943
  • 3
  • 28
  • 41
  • 1
    What if developers of custom file only provided a 32x32 icon? Where do you get a larger image from? Think about this. – westwood Aug 07 '12 at 09:02
  • Thanks @Apokal, I'm happy with whatever I can get. If an app only has small icons, I'll take that, but I know that there are very large icons for things like text files, Office documents, etc. I'd like the best I can get for those ... – MarcWan Aug 09 '12 at 04:36
  • Have you ever found a solution for this? My `BindToHandler` also always returns `E_NOTIMPL` – HelloWorld Jun 21 '21 at 03:44

2 Answers2

7

If you are targeting Vista and higher, you can get a 256x256 icon from the jumbo image list. If you need to target XP, you can at least use the extra large image list, which is 48x48 (slightly better than 32x32 large).

#include <commoncontrols.h>
#include <shellapi.h>

HICON GetHighResolutionIcon(LPTSTR pszPath)
{
    // Get the image list index of the icon
    SHFILEINFO sfi;
    if (!SHGetFileInfo(pszPath, 0, &sfi, sizeof(sfi), SHGFI_SYSICONINDEX)) return NULL;

    // Get the jumbo image list
    IImageList *piml;
    if (FAILED(SHGetImageList(SHIL_JUMBO, IID_PPV_ARGS(&piml))) return NULL;

    // Extract an icon
    HICON hico;
    piml->GetIcon(sfi.iIcon, ILD_TRANSPARENT, &hico);

    // Clean up
    piml->Release();

    // Return the icon
    return hico;
}
Raymond Chen
  • 44,448
  • 11
  • 96
  • 135
  • 5
    One problem: If the image ONLY has 32x32, this function will still return a 256x256 for it, just with the icon in the upper left corner. Is there any way to determine if there's no jumbo icon and just let me fall back to other code? Thanks! – MarcWan Sep 18 '12 at 04:01
  • Tried it and overlays are in fact applied, but the icons are 4-bit with black backgrounds. – jnm2 Jul 21 '17 at 21:35
  • 1
    I'm taking the IShellItemImageFactory.GetImage approach instead, with success. https://stackoverflow.com/a/21752100 – jnm2 Jul 21 '17 at 22:11
1

Have you tried ExtractIconEx()?

It has dedicated parameters to extract arrays of both small and large icons from executables, DLLs, or icon files. From there you can select the size best suited to your needs. The API call is available from Win2K onwards.

U007D
  • 5,772
  • 2
  • 38
  • 44
  • 2
    I believe ExtractIconEx only get the standard small and "large" icons, from the era when large meant 32x32. – Adrian McCarthy Sep 14 '12 at 20:03
  • @AdrianMcCarthy I give it a try and you are correct. 32x32 was the largest I could find. – U007D Sep 17 '12 at 01:21
  • Been reading up on this, but it seems as though it maxes out at 48x48, and I don't know the icon index — i only know the file type. Is there some sort of comprehensive solution that'll get me ~100px images given an extension? – MarcWan Sep 17 '12 at 14:25