6
votes

How do I retrieve system image list for given DPI?

When an application is system DPI-aware, the SHGetFileInfo and similar functions return a handle to a correctly scaled system image list. C++ example:

handle =
  SHGetFileInfo(L"", 0, &fileInfo, sizeof(fileInfo),
                SHGFI_SYSICONINDEX | (large ? SHGFI_LARGEICON : SHGFI_SMALLICON));

But with per-monitor DPI awareness, that's not enough, as the application can run on a monitor that does not use system DPI (or the application can have multiple windows, each on different monitor, with different DPI).

For example, on 168 DPI (175% zoom) monitor, with standard 96 system DPI, you get small unscaled 16x16 icons:

unscaled system icons

So I'm hoping, that there's a DPI-aware variant to the SHGetFileInfo (or similar), the way there are DPI aware variants of other functions like:

1
Ah, I have code that instructs SHGetImageList to return the jumbo 256x256 icons if that's what you need. Upon looking at it again I suspect I originally got it from hereMickyD
@MickyD Because that's not the "right" solution. Icon designers will put more detail in jumbo icons and for small icons, e.g. 16px they omit that detail and create bespoke variants.David Heffernan
HIMAGELIST hImageList = reinterpret_cast<HIMAGELIST>(IImageList); fwiw.Jonathan Potter
There are only 4 sizes, you just have to pick the closest one based on DPI and scale as appropriate.Jonathan Potter

1 Answers

3
votes

As a quick solution, I ended up using SHGetImageList, as suggested by @MickyD.

As mentioned in the function documentation (and as suggested by @JonathanPotter):

The IImageList pointer type, such as that returned in the ppv parameter, can be cast as an HIMAGELIST as needed; for example, for use in a list view.

Hence I use the SHGetImageList to collect all available system image lists sizes by calling it for 0..SHIL_LAST.

For each returned image list, I query its icon size using ImageList_GetIconSize and cache them all.

Then, when an image list is needed for a particular DPI, I pick the closest size available.

An obvious drawback is that on multi monitor systems with high system DPI, but with one low DPI monitor, one cannot retrieve reasonable size of small icons for the low DPI monitor.