The MASM Forum

General => The Workshop => Topic started by: Professor on July 29, 2024, 09:42:53 AM

Title: How to add 32-bit icons
Post by: Professor on July 29, 2024, 09:42:53 AM
As an assembler programmer dating back to the 1970s (when code size was critical), I have a long-standing addiction to efficiency. To this day, I use assembler to make tiny apps, despite ever more abundant RAM and resources making this unnecessary. But I guess I don't need to preach to the converted, right?

When I first delved into MASM back in 2006, one of my first apps was JPGExtra, which removes metadata from JPG files. Back then, I wanted to make the app available to others, so it needed an icon. But it bothered me that adding icons of the recommended sizes and color depths would more than double the size of the app!

With no easy way of generating monochrome icons, I wrote my own code to create them. The resulting icons were added to the startup code using the familiar code snippets during startup:

INVOKE LoadIcon, wc.hInstance, IanIcon16 ;16x16 Icon embedded in resource file
MOV wc.hIconSm, EAX
INVOKE LoadIcon, wc.hInstance, IanIcon32 ;32x32 Icon
MOV wc.hIcon, EAX

All has worked well until more recent versions of Windows, which don't seem to be quite as happy with monochrome icons. Windows seems to lose track of a monochrome icon, replacing it with the icon from another random app. This happens to an app that's running, affecting the taskbar icon and the icon on switching tasks. It also happens to an icon on the desktop or within a folder.

In an effort to accept the inevitable, I made 16-color icons. A compromise between better support without excessive bloat. I once again wrote my own code to create them. These worked – but I must say that I didn't really like the look of them!

My original monochrome icons had some individual personality. They were pure black and white, with a jagged, pixelated look. For my newer 16-color icons, I had the luxury of greyscale to make for smoother internal detail. However, thanks to icons having only a 1-bit image mask, the outer edges still look pixelated.

Which brought me to the inevitable next level: 32-bit icons. No problems creating the icons using today's software. The only problem is integrating them. The above code didn't work. I've probably spent a month reading through discussions, both here on MASM32 as well as on StackOverflow and elsewhere. The only thing I've gleaned is that I should be using "LoadImage" rather than "LoadIcon", but I'm hazy on the specifics.

From my end, I don't need to to do anything else with the image/icon except hand them over to Windows.

Any help would be greatly appreciated!
Title: Re: How to add 32-bit icons
Post by: NoCforMe on July 29, 2024, 09:53:28 AM
Just a quick reply after first reading your post.

Yes, use LoadImage() instead of LoadIcon(). It's what I use, and I'm able to load 32-bit icons with it:
INVOKE LoadImage, InstanceHandle, ADDR fileOpenName, IMAGE_ICON, 0, 0, LR_LOADFROMFILE

(take out LR_LOADFROMFILE if you're including the icon in the .exe as a resource, and replace ADDR fileOpenName with the resource ID of the icon)

I haven't played with monochrome icons. Surprised they don't seem to work for you. Maybe I'll put together a little testbed and see if I can get them to work.
Title: Re: How to add 32-bit icons
Post by: Professor on July 29, 2024, 10:09:12 AM
Quote from: NoCforMe on July 29, 2024, 09:53:28 AM INVOKE LoadImage, InstanceHandle, ADDR fileOpenName, IMAGE_ICON, 0, 0, LR_LOADFROMFILE

Thanks for that! It prompts two follow-up questions:

1. Do I also set "ADDR fileOpenName" to Null if I'm not loading from a file? Or do I set this to the numeric constant for the icon id?

(edit) Oops, I see you answered this already, sorry!

2. Do I then use the same startup code to set the returned image handle as the icon handle?

MOV wc.hIconSm, EAX
MOV wc.hIcon, EAX

You also wrote:

Quote from: NoCforMe on July 29, 2024, 09:53:28 AMI haven't played with monochrome icons. Surprised they don't seem to work for you. Maybe I'll put together a little testbed and see if I can get them to work.

I just tried uploading my icons for you to play with but MASM32's image upload doesn't support .ico files.
Title: Re: How to add 32-bit icons
Post by: NoCforMe on July 29, 2024, 10:31:56 AM
Quote from: Professor on July 29, 2024, 10:09:12 AM2. Do I then use the same startup code to set the returned image handle as the icon handle?

Code Select Expand
MOV wc.hIconSm, EAX
MOV wc.hIcon, EAX

Yes. You can also use WM_SETICON to set your window's icon after registering the window class:
INVOKE SendMessage, <window handle>, WM_SETICON, ICON_BIG, <icon handle>

QuoteI just tried uploading my icons for you to play with but MASM32's image upload doesn't support .ico files.
You can attach any kind of file here by putting it into a .zip archive and attaching that.
Title: Re: How to add 32-bit icons
Post by: NoCforMe on July 29, 2024, 10:49:11 AM
Before we go further, are you familiar with Micro$oft's "Learn" document repository? It's huuuuge and has info on practically every function, structure, message, constant, etc.

So big that you need some entry points into it. Here are two that I use:

If you need to search the repository, I find you first need to land on one of the pages from one of these links, and then type your search query in. Otherwise you get all kinds of spurious results (like non-Windows stuff).

It's not that I mind answering your questions, not at all. It just might be faster for you to be able to look stuff before having to ask.
Title: Re: How to add 32-bit icons
Post by: Professor on July 29, 2024, 10:56:27 AM
Thanks, NoCforMe, that worked as easily as expected. Much appreciated!

QuoteYes. You can also use WM_SETICON to set your window's icon after registering the window class:
    INVOKE    SendMessage, <window handle>, WM_SETICON, ICON_BIG, <icon handle>

I notice that you've included the constant 'ICON_BIG'. I'd been wondering how to overcome other "legacy" calls, as the previous code only seemed to be geared towards the 16x16 and 32x32 icons. Perhaps this single call also allow me to dispense with multiple calls and the embedding of multiple icon files? I've been able to successfully embed multiple icons of different sizes and color depths into the one .ico file but haven't yet worked out how these should be added. I'll do some experimentation now and see where it takes me.

QuoteYou can attach any kind of file here by putting it into a .zip archive and attaching that.

How does one attach a .zip? I only see buttons for adding a YouTube video, image, link or e-mail, while the "Add image to post" only allows me to add images.

Thanks again for helping me overcome these hurdles, NoCforMe.
Title: Re: How to add 32-bit icons
Post by: Professor on July 29, 2024, 11:07:49 AM
Quote from: NoCforMe on July 29, 2024, 10:49:11 AMBefore we go further, are you familiar with Micro$oft's "Learn" document repository? It's huuuuge and has info on practically every function, structure, message, constant, etc.

So big that you need some entry points into it. Here are two that I use:
  • Functions in alphabetical order (https://learn.microsoft.com/en-us/previous-versions//aa383688(v=vs.85)?redirectedfrom=MSDN)
  • Functions by category (https://learn.microsoft.com/en-us/previous-versions//aa383686(v=vs.85)?redirectedfrom=MSDN)

If you need to search the repository, I find you first need to land on one of the pages from one of these links, and then type your search query in. Otherwise you get all kinds of spurious results (like non-Windows stuff).

It's not that I mind answering your questions, not at all. It just might be faster for you to be able to look stuff before having to ask.

That's very helpful advice, I appreciate it. I'm someone who doesn't normally ask for help, as I'm a persistent bugger who will search for answers myself. Sadly, this had taken way too long (probably a month) before I finally gave in.

As a matter of interest, I even have a massive reference book (2kg, 800+ pages) dating back to the 1990s that contains much of the info I've ever needed, but it pre-dates 32-bit icons.
Title: Re: How to add 32-bit icons
Post by: NoCforMe on July 29, 2024, 11:12:42 AM
Quote from: Professor on July 29, 2024, 10:56:27 AMI notice that you've included the constant 'ICON_BIG'. I'd been wondering how to overcome other "legacy" calls, as the previous code only seemed to be geared towards the 16x16 and 32x32 icons. Perhaps this single call also allow me to dispense with multiple calls and the embedding of multiple icon files? I've been able to successfully embed multiple icons of different sizes and color depths into the one .ico file but haven't yet worked out how these should be added.

So what are you ultimately doing with your icons: simply using them as window icons?

The other option with WM_SETICON is, as you might have guessed, ICON_SMALL. For a window icon (what's displayed in the upper-left corner of the window and on the taskbar), you want the "big" one.

QuoteHow does one attach a .zip? I only see buttons for adding a YouTube video, image, link or e-mail, while the "Add image to post" only allows me to add images.
You have to use the Reply button, not the "Quick Reply" panel which lacks the file attachment option.
Title: Re: How to add 32-bit icons
Post by: NoCforMe on July 29, 2024, 11:14:02 AM
Quote from: Professor on July 29, 2024, 11:07:49 AMAs a matter of interest, I even have a massive reference book (2kg, 800+ pages) dating back to the 1990s
Let me guess: Petzold's book (aka doorstop)? I've got a copy. Very useful, but out of date.
Title: Re: How to add 32-bit icons
Post by: Professor on July 29, 2024, 11:16:13 AM
I've posted the .zip to a temporary folder on my website:
JPGExtra icons, 1-bit to 32-bit (https://www.fieggen.com/_temp/jpgextra-icons.zip)
Title: Re: How to add 32-bit icons
Post by: Professor on July 29, 2024, 11:25:06 AM
Quote from: NoCforMe on July 29, 2024, 11:14:02 AMLet me guess: Petzold's book (aka doorstop)? I've got a copy. Very useful, but out of date.

Mine is "The Programmer's PC Sourcebook" by Thom Hogan / Microsoft Press. Also suitable as doorstop, or in my case, a book-end for a shelf full of other smaller books.

Funny story: Years ago, one of my fellow PC gurus was using two un-opened copies of a particularly crappy version of DOS, with its nonetheless sturdy, hard-bound manuals, as a printer stand! As he put it: "It's the only reliable use I've seen for this software."
Title: Re: How to add 32-bit icons
Post by: Professor on July 29, 2024, 11:33:49 AM
Quote from: NoCforMe on July 29, 2024, 11:12:42 AMSo what are you ultimately doing with your icons: simply using them as window icons?

Exactly. I'm not doing anything special with them, like adding them to forms or animating them or manipulating them in any way. Just giving them to Windows to use in the various scenarios such as you've mentioned.

I take it then that I still need to do separate calls for the different icon sizes? It therefore seems to be fairly pointless to create a single icon file containing multiple icon resources – except for a tiny saving in file overhead.
Title: Re: How to add 32-bit icons
Post by: NoCforMe on July 29, 2024, 12:10:20 PM
Quote from: Professor on July 29, 2024, 11:33:49 AMI take it then that I still need to do separate calls for the different icon sizes? It therefore seems to be fairly pointless to create a single icon file containing multiple icon resources – except for a tiny saving in file overhead.

Not sure why you'd need to load different sizes.
In my programs (which are dialog based: I use a dialog as the main window, instead of creating a main window with CreateWindowEx()), I use the call I showed above, with ICON_BIG. That seems to take care of setting the window icon properly.

For the icon that represents the executable, I simply set that in my resource file (using a 32x32 icon).

I'm running Windows 7; things may have changed in subsequent versions of the OS. What version are you using?
Title: Re: How to add 32-bit icons
Post by: Professor on July 29, 2024, 12:20:48 PM
Quote from: NoCforMe on July 29, 2024, 12:10:20 PMNot sure why you'd need to load different sizes.
In my programs (which are dialog based: I use a dialog as the main window, instead of creating a main window with CreateWindowEx()), I use the call I showed above, with ICON_BIG. That seems to take care of setting the window icon properly.

For the icon that represents the executable, I simply set that in my resource file (using a 32x32 icon).

Icons with any level of detail can look awful when scaled down to only 16x16 pixels. I've always believed in the policy of creating a second, simpler 16x16 icon. While I was at it, I created a larger, 48x48 icon for when the icon appears in a folder, on the desktop, etc.
Title: Re: How to add 32-bit icons
Post by: Professor on July 30, 2024, 01:59:18 PM
Just a quick follow-up that the .asm now compiles perfectly and the resulting 32-bit icons look great. The finished .exe is now 35kb (previously 23kb with mono icons).

That said, Windows (my version = 8.1) is still exhibiting strange behavior when displaying the icons. The freshly-minted app with its new icon looks perfect when sitting in a folder on the D: drive (where my code resides). But when copied to the C: drive, Explorer shows the old monochrome icon! Even deleting the file from the C: drive, then re-copying the new file from the D: drive, would still show to old icon! Obviously Windows is doing some form of caching. I got over that by copying it with a different filename, then renaming the copied file.

The experiments continue...
Title: Re: How to add 32-bit icons
Post by: stoo23 on July 30, 2024, 02:43:07 PM
Gee, I think I'd be wanting to 'ditch' Windows 8.1 and move to Windows 10.
You may find it all just works better  :smiley:
Title: Re: How to add 32-bit icons
Post by: NoCforMe on July 30, 2024, 02:47:21 PM
Does that unwanted behavior survive a reboot?
Title: Re: How to add 32-bit icons
Post by: TimoVJL on July 30, 2024, 02:51:13 PM
This link give some details:
deleting the IconCache.db file (https://answers.microsoft.com/en-us/windows/forum/all/deleting-the-iconcachedb-file/1f47e9ea-21d1-4c5a-9985-3d076bfd6606)
Title: Re: How to add 32-bit icons
Post by: jj2007 on July 30, 2024, 09:42:46 PM
Try converting the *.ico to *.png

I can't test it right now.
Title: Re: How to add 32-bit icons
Post by: Professor on August 01, 2024, 11:21:48 AM
Quote from: stoo23 on July 30, 2024, 02:43:07 PMGee, I think I'd be wanting to 'ditch' Windows 8.1 and move to Windows 10.
You may find it all just works better  :smiley:

You could be right. That said, I'm not always convinced by the relentless drive forwards. Continuously adding complexity doesn't guarantee reduced problems!
Title: Re: How to add 32-bit icons
Post by: stoo23 on August 01, 2024, 11:26:38 AM
I only suggest it as had a good old friend that had been having endless weird issues with her 8.1 laptop.
Once upgraded to 10,.. she had no further problems.

QuoteContinuously adding complexity doesn't guarantee reduced problems!
Understood but you ARE virtually there anyway,.. 8.1 is just a rather Badly formed 10  :smiley:

I honestly Don't think you would be wishing you didn't upgrade after doing so  :wink2:
Title: Re: How to add 32-bit icons
Post by: jj2007 on August 01, 2024, 03:39:32 PM
Quote from: stoo23 on August 01, 2024, 11:26:38 AM8.1 is just a rather Badly formed 10

I jumped from 7 to 10 and confirm that Win10 is running rather smoothly. Hutch, btw, also liked Win10. But I will continue to ignore the invitation to install Win11 on this machine. That one must mature a couple of years :cool:
Title: Re: How to add 32-bit icons
Post by: Professor on August 01, 2024, 04:12:00 PM
Quote from: jj2007 on July 30, 2024, 09:42:46 PMTry converting the *.ico to *.png

I'm loving the idea that Windows has moved on from the dated .ico format and is now embracing the far more versatile .png format. I immediately tried this, only to get the following compilation error:
JPGExtra3.rc (4): error RC2175 : resource file JPGExtra_48x48_v2_32bit.png is not in 3.00 format

Microsoft's help pages aren't particularly helpful:
The specified resource used a format earlier than version 3.00. The resource file must be converted or recreated using the format for version 3.00 or later.

I'll keep experimenting...
Title: Re: How to add 32-bit icons
Post by: jj2007 on August 01, 2024, 05:37:02 PM
See this SOF post (https://stackoverflow.com/questions/58751417/how-can-i-add-a-transparent-png-as-a-toolbar-icon). The second answer involves Gdi+, maybe that's a way to do it. I don't have time to test it right now, sorry...
Title: Re: How to add 32-bit icons
Post by: stoo23 on August 01, 2024, 06:16:42 PM
QuoteI jumped from 7 to 10 and confirm that Win10 is running rather smoothly
Yeah, so did I on the laptop, it was well configured i7 8 gig ram etc and the update process went very smoothly and the machine has been faultless since the upgrade !!

I like Win 7 but also am completely happy with the Win 10 installations I have  :thumbsup:
Title: Re: How to add 32-bit icons
Post by: Professor on August 01, 2024, 06:36:35 PM
Quote from: jj2007 on August 01, 2024, 05:37:02 PMSee this SOF post (https://stackoverflow.com/questions/58751417/how-can-i-add-a-transparent-png-as-a-toolbar-icon). The second answer involves Gdi+, maybe that's a way to do it. I don't have time to test it right now, sorry...

Interesting – thanks! I wasn't aware of the 32-bit "premultiplied alpha" bitmap format.
Title: Re: How to add 32-bit icons
Post by: Professor on August 01, 2024, 06:41:17 PM
Thanks also to various folks for their advice on Win-10. About a year ago I upgraded my partner's computer to Win-10 (I've been a PC specialist since the 1990s) and it had been mostly smooth sailing ever since. Her bluetooth-enabled hearing aids now get intermittent audio, so we reverted to good-old-fashioned headphones! (*sigh*)
Title: Re: How to add 32-bit icons
Post by: Professor on January 04, 2025, 05:03:05 PM
After experiencing much frustration with all of this back in August, I finally gave in, resigning myself to revisiting the issue with a fresh mind at a later date. And so here we are in the New Year!

This is where I'm at currently – hopefully some of this helps others.

My original approach had three separate .ico files specified in the resource file – one each for 48x48, 32x32 and 16x16 pixels. When my program starts, I load the 32x32 icon, feed the handle to "wc.hIcon", load the 16x16 icon, feed that handle to "wc.hIconSm". Easy enough!

Windows Explorer would also display the embedded 48x48 icon when the .exe was viewed on the desktop or in a folder. When Explorer's folder view was changed to "Extra large icons" or "Large icons", the icon was small but still adequate. However, when the view was set to "Small icons", "List" or "Details", for which it *should* load the 16x16 icon, it instead rescaled that 48x48 down to 16x16 – which looked awful.

I could instead have the 16x16 icon appear first in the resource file, with the opposite result of showing the 16x16 icon in each different view. Not great either! In addition, the 48x48 icon then goes to waste – unless someone specifically creates a shortcut and changes the icon to the third one listed.

Okay, that was my original approach. After much research, I finally hit on the solution.

Windows Explorer will always load the first – or lowest numbered – icon resource from the .exe file. However, if that icon resource contains more than one size of icon, Explorer will load the appropriate sized icon to suit the view.

I therefore created a single .ico file containing all three sizes: 48x48, 32x32 and 16x16. I then found how to set the correct parameters to "LOADIMAGE" to similarly load the correct sized icon from that single icon file.

Just to be safe, rather than hard-code my source with "16" or "32" for the "cx" and "cy" parameters, I figured it would be better to allow for computer setups where people have adjusted their system to display larger or smaller icons than the "standard" sizes.

Here, then, is the final code that worked:

Resource file:
#define IanIcons 100
IanIcons ICON DISCARDABLE JPGExtra_v2_483216x32.ico

Assembler file:
IanIcons        EQU 100                ;48/32/16 x 32-bit icons
...
INVOKE GetSystemMetrics, SM_CXICON            ;Large icon width
INVOKE LoadImage, wc_hInstance, IanIcons, IMAGE_ICON, EAX, EAX, LR_SHARED
MOV wc_hIcon, EAX
INVOKE GetSystemMetrics, SM_CXSMICON            ;Small icon width
INVOKE LoadImage, wc_hInstance, IanIcons, IMAGE_ICON, EAX, EAX, LR_SHARED
MOV wc_hIconSm, EAX

All's good now – except for implementing 256x256 pixel icons. Try as I might, I haven't been able to succeed with these! The error always occurs at the resource compiler stage. I get one of two messages:

JPGExtra3.rc (8): error RC2176 : old DIB in JPGExtra_v2_256x32.ico; pass it through SDKPAINT
- or -
JPGExtra3.rc (8): error RC2175 : resource file JPGExtra_v2_256x32.bmp is not in 3.00 format

I'm guessing these are due to an older version of rc.exe? In any case, I'm not that keen on quadrupling the finished size of my nice tiny .exe file, so I'll leave it for another day. The small icons are more than sufficient for their task.
Title: Re: How to add 32-bit icons
Post by: Villuy on February 04, 2025, 02:58:02 AM
You not need to shove many pictures of different resolutions in file ico. Put 1 picture png 256 x 256 in ico. Windows perfectly scales this large picture to fit any situation.

Create file res from modern ico:

https://masm32.com/board/index.php?topic=12484.0 (https://masm32.com/board/index.php?topic=12484.0)
Title: Re: How to add 32-bit icons
Post by: daydreamer on February 04, 2025, 05:29:42 AM
Quote from: Villuy on February 04, 2025, 02:58:02 AMYou not need to shove many pictures of different resolutions in file ico. Put 1 picture png 256 x 256 in ico. Windows perfectly scales this large picture to fit any situation.

Create file res from modern ico:

https://masm32.com/board/index.php?topic=12484.0 (https://masm32.com/board/index.php?topic=12484.0)
Are you annoyed by vc++ wizard produces 120 kb cpp exe,replace those 2x 50kb. Ico files with one tiny compressed few kb. Ico instead and you get ca 22 kb exe instead
Title: Re: How to add 32-bit icons
Post by: Villuy on February 04, 2025, 06:38:17 AM
Quote from: daydreamer on February 04, 2025, 05:29:42 AMAre you annoyed by vc++ wizard produces 120 kb cpp exe,replace those 2x 50kb. Ico files with one tiny compressed few kb. Ico instead and you get ca 22 kb exe instead

I am annoyed?    :undecided: