News:

Masm32 SDK description, downloads and other helpful links
Message to All Guests
NB: Posting URL's See here: Posted URL Change

Main Menu

How to add 32-bit icons

Started by Professor, July 29, 2024, 09:42:53 AM

Previous topic - Next topic

Professor

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!

NoCforMe

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.
Assembly language programming should be fun. That's why I do it.

Professor

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.

NoCforMe

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.
Assembly language programming should be fun. That's why I do it.

NoCforMe

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.
Assembly language programming should be fun. That's why I do it.

Professor

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.

Professor

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:

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.

NoCforMe

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.
Assembly language programming should be fun. That's why I do it.

NoCforMe

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.
Assembly language programming should be fun. That's why I do it.

Professor

I've posted the .zip to a temporary folder on my website:
JPGExtra icons, 1-bit to 32-bit

Professor

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."

Professor

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.

NoCforMe

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?
Assembly language programming should be fun. That's why I do it.

Professor

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.

Professor

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...