I doubt many are unaware, but some probably are. So let me start by stating the limitations of using LoadResPicture with the vbResIcon and vbResCursor options while in the IDE.
1. Cannot specify the size of the loaded icon. Always loaded as default (32x32 in 100% DPI)
2. Icons/cursors having color depths other than the screen will not be used. Assumes more than one bit depth is provided in the icon resource.
3. Cursors are always loaded/scaled to a default size
4. Cursors are loaded black and white in IDE, but color when compiled.
By using a couple of APIs to find and load a specified icon/cursor, we can force VB to use the size we want. Problem numbers 1, 2 and 4 above are overcome by this method. Problem number 3 remains but, typically, is expected behavior. When compiled, LoadImage() API can be used to retrieve desired icon sizes as an HICON which can be wrapped in a stdPicture. When compiled, that API solves problem number 1. Problem number 4 doesn't exist once compiled.
Here are a couple scenarios regarding icons.
Scenario 1: You have an icon file containing only a 128x128 image. If you set that icon, in design, to a VB picture property, you get a 128x128 icon. But if you add it to your resource file then use something like Me.Picture = LoadResPicture(##, vbResIcon), what you get is a scaled-down 32x32 icon.
Scenario 2: You have an icon file with multiple images of varying sizes and color/bit depths. If you set that icon to a VB picture property, you get the first image in the file and cannot choose a size or color depth. If you add the icon file to a resource file, LoadResPictre returns a 32x32 icon if it exists, else function selects an icon and scales it to 32x32.
By using a couple of APIs, we can ask Windows to select the icon size we want when the icon file, added to a resource file, contains multiple sized images. Even if we wanted a size not in the file, we can ask that it be scaled for us. This method works whether compiled or not.
Caveats...
1. Though the code will load a 32bpp icon (XP+) and those containing PNG compression (Vista+), VB still may not display it correctly. These types of icons may fail to be loaded via the resource editor. Adding these types of icons may require alternate tools like the Microsoft RC.exe application. Icons larger than 255x255 may also require such tools.
2. If you have an icon resource that contains multiple images of varying sizes and depths, it is assumed that for each size, you have the same number of icons per depth. For example, if having icon sizes of 16, 32, 48 and depths of 8 and 32 bits, it is expected you have 6 icons, an 8 and 32 bit version for each size. This assumption is a requirement if you use the code's option to select an icon of a specific color depth. After all, this is your project and you dictate what gets added to the resource file and what doesn't. Therefore, you shouldn't be asking for a color depth that doesn't exist.
3. This method is capable of properly finding/loading PNG-encoded icons (Vista+), but the VB Resource Editor breaks that. The Resource Editor doesn't know how to deal with these (editor code is too old and not updated). It assumes the bitcount and planes attributes of the image is at a fixed offset from where the icon data starts. That assumption fails for PNG encoding as those offsets point to the PNG IHDR chunk. Therefore, the bitcount is always reported 21060 and planes as 18505 which is part of that chunk. No API that looks at this invalid icon directory structure is going to be able to process it correctly -- it is in-effect corrupted. Use another tool to add PNG-encoded icons to the resource file. However, if the PNG image is the only one in the resource, it will be selected.
Above being said, even if the directory structure isn't corrupted, if you have icons of sizes 256x256 and 512x512, they are likely PNG compressed. However, when asking for one of those, the 1st one in the icon file will be used and scaled as needed. This is because the APIs being used cannot distinguish between icon sizes larger than 255x255. Reason is that width/height are each defined by a single byte. Max value of a single byte is 255. The value of zero basically means: larger than 255. This can be worked around and will consider it if wanted. The Vista API mentioned below may not have that problem but not tested it and it is not compatible with uncompiled projects. I'd suspect that API checks the icon's actual size vs. relying on the size provided in the icon directory structure -- that's the way I'd do it ;)
FYI... LoadIconWithScaleDown is a newer API function that requires at least Vista and also cannot be used unless project is compiled. That function allows you to do what this code does but, again, not while uncompiled. That API also works with icon files on disc.
Post# 2 has the code. The zip below has a sample project with methods included.
The included resource file has one icon with just a 128x128 image, another icon with 9 images ranging from 16x16 to 128x128 and a cursor with 2 images: 32x32, 48x48. All icons and cursors are 8 bit.
1. Cannot specify the size of the loaded icon. Always loaded as default (32x32 in 100% DPI)
2. Icons/cursors having color depths other than the screen will not be used. Assumes more than one bit depth is provided in the icon resource.
3. Cursors are always loaded/scaled to a default size
4. Cursors are loaded black and white in IDE, but color when compiled.
By using a couple of APIs to find and load a specified icon/cursor, we can force VB to use the size we want. Problem numbers 1, 2 and 4 above are overcome by this method. Problem number 3 remains but, typically, is expected behavior. When compiled, LoadImage() API can be used to retrieve desired icon sizes as an HICON which can be wrapped in a stdPicture. When compiled, that API solves problem number 1. Problem number 4 doesn't exist once compiled.
Here are a couple scenarios regarding icons.
Scenario 1: You have an icon file containing only a 128x128 image. If you set that icon, in design, to a VB picture property, you get a 128x128 icon. But if you add it to your resource file then use something like Me.Picture = LoadResPicture(##, vbResIcon), what you get is a scaled-down 32x32 icon.
Scenario 2: You have an icon file with multiple images of varying sizes and color/bit depths. If you set that icon to a VB picture property, you get the first image in the file and cannot choose a size or color depth. If you add the icon file to a resource file, LoadResPictre returns a 32x32 icon if it exists, else function selects an icon and scales it to 32x32.
By using a couple of APIs, we can ask Windows to select the icon size we want when the icon file, added to a resource file, contains multiple sized images. Even if we wanted a size not in the file, we can ask that it be scaled for us. This method works whether compiled or not.
Caveats...
1. Though the code will load a 32bpp icon (XP+) and those containing PNG compression (Vista+), VB still may not display it correctly. These types of icons may fail to be loaded via the resource editor. Adding these types of icons may require alternate tools like the Microsoft RC.exe application. Icons larger than 255x255 may also require such tools.
2. If you have an icon resource that contains multiple images of varying sizes and depths, it is assumed that for each size, you have the same number of icons per depth. For example, if having icon sizes of 16, 32, 48 and depths of 8 and 32 bits, it is expected you have 6 icons, an 8 and 32 bit version for each size. This assumption is a requirement if you use the code's option to select an icon of a specific color depth. After all, this is your project and you dictate what gets added to the resource file and what doesn't. Therefore, you shouldn't be asking for a color depth that doesn't exist.
3. This method is capable of properly finding/loading PNG-encoded icons (Vista+), but the VB Resource Editor breaks that. The Resource Editor doesn't know how to deal with these (editor code is too old and not updated). It assumes the bitcount and planes attributes of the image is at a fixed offset from where the icon data starts. That assumption fails for PNG encoding as those offsets point to the PNG IHDR chunk. Therefore, the bitcount is always reported 21060 and planes as 18505 which is part of that chunk. No API that looks at this invalid icon directory structure is going to be able to process it correctly -- it is in-effect corrupted. Use another tool to add PNG-encoded icons to the resource file. However, if the PNG image is the only one in the resource, it will be selected.
Above being said, even if the directory structure isn't corrupted, if you have icons of sizes 256x256 and 512x512, they are likely PNG compressed. However, when asking for one of those, the 1st one in the icon file will be used and scaled as needed. This is because the APIs being used cannot distinguish between icon sizes larger than 255x255. Reason is that width/height are each defined by a single byte. Max value of a single byte is 255. The value of zero basically means: larger than 255. This can be worked around and will consider it if wanted. The Vista API mentioned below may not have that problem but not tested it and it is not compatible with uncompiled projects. I'd suspect that API checks the icon's actual size vs. relying on the size provided in the icon directory structure -- that's the way I'd do it ;)
FYI... LoadIconWithScaleDown is a newer API function that requires at least Vista and also cannot be used unless project is compiled. That function allows you to do what this code does but, again, not while uncompiled. That API also works with icon files on disc.
Post# 2 has the code. The zip below has a sample project with methods included.
The included resource file has one icon with just a 128x128 image, another icon with 9 images ranging from 16x16 to 128x128 and a cursor with 2 images: 32x32, 48x48. All icons and cursors are 8 bit.