I have an icon file that contains a 24x24, 32x32, 48x48, 64x64, and 256x256 icon. However, when I load it like this:
Application->Icon->LoadFromFile("filename.ico");
it appears to only load the one image from the file, despite the fact that my icon contains multiple resolutions of the icon. The result is that any Forms use the single icon re-scaled for both the taskbar icon, and the corner icon, which looks bad.
However, if I set filename.ico into a compiled resource, or if I set the icon in Project Properties > Application > Icon, then my Forms use the 24x24 icon for the corner icon, and the 48x48 icon for the taskbar.
My question is: how can I have my Forms use the icons from filename.ico where the filename is not known until runtime; but still use the 24x24 icon for the corner and use the 48x48 icon for the taskbar?
NB. I prefer not to hardcode those sizes 24x24, and 48x48, because other versions of Windows (or if the person uses the windows font scaling option) may then call for a different size icon.
When you call
TIcon.LoadFrom...(), it stores a copy of the raw icon data into an internal memory block and then exits. That block is not processed until the next time thatTIcon.HandleNeeded()is called, such as when theTIcon.Handleproperty is used.If the icon data represents an icon of type
RC3_STOCKICON(not usually encountered), theIDI_APPLICATIONicon fromLoadIcon()is used. Otherwise, if the icon data represents an icon of typeRC3_ICON(the usual case), the data is parsed and the image that most closely matches the currentTIcon.WidthandTIcon.Heightproperty values (or theSM_CXICONandSM_CYICONmetrics viaGetSystemMetrics()if theTIcondimensions have not been assigned yet) are passed toCreateIcon().From that point on, the
HICONreturned byLoadIcon()orCreateIcon()is the image used for the remainder of theTIcon's lifetime, or at least until theHICONis freed/released viaTIcon.ReleaseHandle(),TIcon.Assign(),TIcon.LoadFrom...(),TIcon.SetHandle(), etc.The memory block itself is only freed when the
TIconis freed,TIcon.Assign()is called, or a new image source is loaded. So it should be possible, for instance, to callTIcon.ReleaseHandle()to release the currentHICON(you will then have to free it manually viaDestroyIcon()), then resize theTIcon's dimensions, and then callTIcon.HandleNeeded()to re-parse the memory block to load the next closest matching image.Update:
TIconcannot have multiple images of different resolutions loaded at the same time. AForm's corner icon and its Taskbar icon (and remember, whenApplication->MainFormOnTaskbaris false, the Taskbar button is controlled by the hiddenApplicationwindow, not theMainFormwindow, unless you override that behavior manually) are actually separate icons at the OS layer, assigned via theWM_SETICONmessage using different input parameters (wParam=ICON_SMALLandwParam=ICON_BIG, respectively). However, the VCL only ever usesWM_SETICONto set a window's BIG icon, never its SMALL icon. So aForm's corner icon is just a scaled down version of its Taskbar icon (whenMainFormOnTaskbaris true) or theApplication's Taskbar button (whenMainFormOnTaskbaris false). When the VCL issuesWM_SETICONfor aForm, it used theForm's ownIconif assigned, otherwise it uses theApplication'sIconif assigned, otherwise it usesLoadIcon()to load the defaultIDI_APPLICATIONicon.So, if you really want different icons of different resolutions for the
Form's corner icon and Taskbar icon, you will have to use separateTIconobjects to load the desired resolution images, as described above, and then issue your ownWM_SETICONmessages accordingly.