How do I get a high resolution icon for a file?

Today's Little Program obtains a high resolution icon for a file.

Start with our scratch program and make these changes. Remember, Little Programs do little or no error checking. This week's smart pointer class is (rolls dice) _com_ptr_t!

#include <shlwapi.h>
#include <commoncontrols.h>
#include <comip.h>
#include <comdef.h>

_COM_SMARTPTR_TYPEDEF(IImageList, __uuidof(IImageList));

HICON g_hico;

HINSTANCE g_hinst;                          /* This application's HINSTANCE */

int GetIconIndex(PCTSTR pszFile)
  SHGetFileInfo(pszFile, 0, &sfi, sizeof(sfi), SHGFI_SYSICONINDEX);
  return sfi.iIcon;

HICON GetJumboIcon(int iImage)
  IImageListPtr spiml;
  SHGetImageList(SHIL_JUMBO, IID_PPV_ARGS(&spiml));

  HICON hico;
  spiml->GetIcon(iImage, ILD_TRANSPARENT, &hico);
  return hico;

The Get­Icon­Index function does nothing new. It simply retrieves the system image list icon index for a file's icon.

The Get­Jumbo­Icon retrieves an icon by its system image list index. First, it asks SHGet­Image­List for the jumbo image list, then it asks the jumbo image list for the icon.

Now all we have to do is hook the functions up.

PaintContent(HWND hwnd, PAINTSTRUCT *pps)
  DrawIconEx(pps->hdc, 50, 50, g_hico,
             0, 0, 0, nullptr, DI_NORMAL);

    if (SUCCEEDED(CoInitialize(NULL))) {/* In case we use COM */

        g_hico = GetJumboIcon(GetIconIndex(lpCmdLine));


Run this program and pass the full path to a file on the command line. (No quotation marks, even if it contains spaces!) Result: A gigantic icon for the file appears.

Instead of converting the system imagelist index into an icon, we could just ask the jumbo imagelist to render it directly.

int g_iImage;

PaintContent(HWND hwnd, PAINTSTRUCT *pps)
  IImageListPtr spiml;
  SHGetImageList(SHIL_JUMBO, IID_PPV_ARGS(&spiml));

  IMAGELISTDRAWPARAMS ildp = { sizeof(ildp) };
  ildp.himl = IImageListToHIMAGELIST(spiml);
  ildp.i = g_iImage;
  ildp.hdcDst = pps->hdc;
  ildp.x = 50;
  ildp.y = 50;
  ildp.rgbBk = CLR_NONE;
  ildp.fStyle = ILD_TRANSPARENT;

    if (SUCCEEDED(CoInitialize(NULL))) {/* In case we use COM */

        g_iImage = GetIconIndex(lpCmdLine);

        // no cleanup necessary

This is how Explorer deals with icons most of the time. It doesn't create actual icons; it merely remembers indices into the system imagelist, and when it needs to draw an icon, it calls the Draw method on the imagelist whose size corresponds to the image it wants.

Bonus chatter: The system imagelists come in four sizes (as of this writing). And yet large is one of the smallest available ones. Why is that?

The system imagelist sizes are

  • Small
  • Large
  • Extra-Large
  • Jumbo

The first two (small and large) were the only ones available in Windows 95. Windows XP added a size larger than large, which was named extra-large. And then Windows Vista added another size even larger than extra-large, which I named jumbo.

It's an artifact of history that one of the smallest icon sizes has the name large. It was the largest icon size at the time, but things got even larger since then.

Comments (10)
  1. Joshua says:






  2. skSdnW says:

    You forgot system metrics small.

    Why did the shell team decide that they needed their own version of small icons?

    [One is for small icons in Explorer. The other is for small icons in the title bar. Or would you have preferred that Explorer small icons be the same size as title bar small icons? -Raymond]
  3. What's next says:


  4. skSdnW says:

    @Raymond: Icons generally don't look that good when scaled and if the DPI is high enough to warrant 24×24 or 32×32 icons in the title bar then you probably want larger icons in explorer as well. That customize classic theme metrics dialog gets more and more hidden in every version and while I use it to make scrollbars thinner I never change the title bar icon.

    @What's next: Bitmap icons cannot be larger than 256×256. The next step would probably be SVG.

    [There were, at the time, a lot of nerds who want teeny-tiny title bars (because they don't want to waste screen space on nonclient pixels), but still have reasonable-sized small icons in the Explorer view (since that is client space). -Raymond]
  5. pmo says:

    A similar thing seems to have happened to radio frequency bands, ending up wirh high/very high/ultra high/super high/extremely high frequency:…/Radio_spectrum

  6. Jon_S says:

    USB suffered from the (IMO) even more confusing naming of Low/Full/Hi/Super speed where, unintuitively, Hi-speed is faster than Full speed.  Full speed is about 1/23rd the speed of Hi; or 1/341st the speed of Super.

    And I wonder what the USAF successor to the AAMRAM (Advanced Medium-Range Air-to-Air Missile) will be?  The "Really Advanced", the "More Advanced", the "Next Gen"?  Looking back at naming schemes that didn't leave room to comfortably fit in future changes can be amusing.

  7. Nicholas says:


    That seems to be what often happens when you reduce technical specifics into the soft fuzzy marketing language that gets printed on the box (or in the case of the AMRAAM, what gets printed on the congressman's 10-line executive summary).  Though the Really Advanced missile might not be a bad idea: RAMRAAM :)

  8. ender says:

    Speaking of icons, is there some way to load the scaled versions of predefined icons (IDI_ASTERISK etc.) when running in non-default DPI modes? So far everything I tried always gave me 32×32 icons.

  9. SI says:

    Why bother starting with small?

    Large Binocular Telescope

    Very Large Telescope

    Extremely Large Telescope

    Giant Magellan Telescope


  10. Jonathan says:

    And that, ladies and gentlemen, is why we have numbers. Indeed, instead of USB's confusing:

    * Low

    * Full

    * Hi

    * Super

    We could have the clear:

    * 1.5

    * 12

    * 480

    * 3000 (or something like that)

    Just make sure you define clearly what the numbers mean, otherwise you'd end up like memory speeds, where the same unit can be described as either DDR2-800, PC2-6400 or 400MHz.

Comments are closed.