2

I want to load and show one of explorer.exe's icons.

I use the following code (abbreviated):

// resource id definition    

EXP_ICON    = MAKEINTRESOURCE(101);      { Explorer's Icon resource ID      }

// load explorer.exe

ExpInstance := LoadLibraryEx(ExpDirectory,
                             0,
                             LOAD_LIBRARY_AS_IMAGE_RESOURCE);

// load the icon from it

ExpIcon := LoadImage(ExpInstance,
                     MAKEINTRESOURCE(EXP_ICON),
                     IMAGE_ICON,            { load the icon  }
                     32,
                     32,
                     LR_LOADREALSIZE);

That code loads the first icon it finds, which happens to be a 16 color icon. There are other icons in the group with more colors (256 and 16 million).

My question is: Is it possible to tell LoadImage() to load one of those icons (those that use more colors), and if so how?

I've tried changing EXP_ICON to one of the icon ordinal IDs, but if the ID is not that of an icon group, LoadImage() does not succeed.

I'm out of ideas to make LoadImage() load an icon with the number of colors I want.

Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
ScienceAmateur
  • 521
  • 4
  • 11

1 Answers1

7

LoadImage is designed to automatically load the icon with the most appropriate color bit depth that has the size you request. By "most appropriate", I mean the one that is the best match for your current display settings. This is almost always exactly what you want, so the function is one of those that "Just Works". Tell it what size (pixel dimensions) icon you want, and it handles the rest. There is no way of telling it which color bit depth you want to use.

If there isn't an icon of that size, it scales up a smaller one. Since this isn't ideal, recent versions of Windows offer the LoadIconWithScaleDown API, which does exactly what it says on the tin. This produces better-looking results. See David Heffernan's answer here for a usage example.

Anyway. Your problem here is unrelated to the LoadImage function. The problem is the LR_LOADREALSIZE flag that you're passing to the function. I can't find a definition of that constant in the Windows SDK header files, but it looks like it is defined by either the Delphi or C++ Builder libraries. The definition is something like:

LR_LOADREALSIZE = $80;

or

#define LR_LOADREALSIZE (Byte)(128)

It is a constant with a hexadecimal value of 0x80. The problem is, when you look at the documentation for the LoadImage function, you see that a hex value of 0x80 is actually the constant LR_VGACOLOR:

LR_VGACOLOR
0x00000080

Uses true VGA colors.

The description is a bit oblique here—you have to know what "true VGA colors" are. The original VGA was a 16-color display system, and that's what is meant here. So, you're getting a 16-color version of the icon because you're specifically asking for it. Remove the LR_LOADREALSIZE flag (which is actually the LR_VGACOLOR flag), and everything will work properly. Just pass 0 as the flag (or LR_DEFAULTCOLOR, which is defined to be 0).

Note: You should not be hard-coding pixel dimensions like 32. Instead, you should be calling the GetSystemMetrics function with the SM_CXICON and SM_CYICON flags. These will give you the actual size of a "normal"-sized icons on the system. "Normally", these icons have a size of 32x32 pixels, but that's not guaranteed, especially in the current era of high-DPI displays. They might be even larger. If you want small icons (normally 16x16), use SM_CXSMICON and SM_CYSMICON, instead.

In the rare case where you actually want to load an icon from a resource or ICO file with a specific color bit depth, and not have the system automatically determine the color depth to load, you will have to load it manually using a sequence like FindResourceLoadResourceLockResourceCreateIconFromResourceEx. See also "Icons" by John Hornick on MSDN (an old article, but still accurate for this stuff), and this blog post by Raymond Chen.

Cody Gray - on strike
  • 239,200
  • 50
  • 490
  • 574
  • 1
    I cannot thank you enough. I read the documentation page for LoadImage about 10 times and missed the fact that LR_LOADREALSIZE was not even on the list, much less that it was the same as LR_VGACOLOR. I agree about the hardcoding, it got there from trying one thing after another I changed the flag to LR_DEFAULTCOLOR and it loaded the 16mil icon which is exactly what I wanted. Thanks again. – ScienceAmateur Feb 11 '19 at 00:13