I have a GUI application which includes a number of icons used for toolbar buttons, menu glyphs, notification icons etc. These icons are linked to the application as resources and a variety of different sizes are available. Typically, for toolbar button images I have available 16px, 24px and 32px versions. My icons are 32bpp with partial transparency.
The application is high DPI aware and adjusts the size of all visual elements according to the prevailing font scaling. So, for example, at 100% font scaling, 96dpi, the toolbar icon size is 16px. At 125% scaling, 120dpi, the toolbar icon size is 20px. I need to be able to load an icon of size 20px without any aliasing effects. How can I do this? Note that I would like to support Windows 2000 and later.
On Vista and up a number of new functions were added that make this task trivial. The function that is most appropriate here is
LoadIconWithScaleDown.In my experience this function does an excellent job of scaling and the results show no signs of aliasing.
For earlier versions of Windows there is, to the very best of my knowledge, no single function that can perform this task adequately. The results obtained from
LoadImageare of very poor quality. Instead the best approach I have found is as follows:This means that there will be a small transparent border around the icon, but typically this is small enough to be insignificant. The ideal option would be to use code that could scale down just as
LoadIconWithScaleDowndoes, but that is non-trivial to write.So, without further ado here is the code I use.
Using these function is quite obvious. They assume that the resource is located in the same module as the code. The code could readily be generalised to receive an
HMODULEin case you needed support for that level of generality.Call
LoadIconResourceMetricif you wish to load icons of size equal to the system small icon or system large icon. TheIconMetricparameter should be eitherICON_SMALLorICON_BIG. For toolbars, menus and notification icons,ICON_SMALLshould be used.If you wish to specify the icon size in absolute terms use
LoadIconResourceSize.These functions return an
HICON. You can of course assign this to theHandleproperty of aTIconinstance. More likely you will wish to add to an image list. The easiest way to do this is to callImageList_AddIconpassing theHandleof theTImageListinstance.Note 1: Older versions of Delphi do not have
LoadIconWithScaleDowndefined inCommCtrl. For such Delphi versions you need to callGetProcAddressto load it. Note that this is a Unicode only API and so you must send it aPWideCharfor the resource name. Like this:LoadIconWithScaleDown(..., PWideChar(WideString(ResourceName)),...).Note 2: The definition of
LoadIconWithScaleDownis flawed. If you call it after the common controls library has been initialised then you will have no problems. However, if you call the function early on in the life of your process thenLoadIconWithScaleDowncan fail. I have just submitted QC#101000 to report this problem. Again, if you are afflicted by this then you have to callGetProcAddressyourself.