News:

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

Main Menu

Dynamically changing toolbar button images

Started by NoCforMe, March 26, 2025, 11:23:55 AM

Previous topic - Next topic

NoCforMe

I just figured out how to do this: change a toolbar button image dynamically.
Not too hard to do, using the standard TB_xxxx messages.

Here's the recipe:

1. Set up the toolbar as usual (see the sub-recipe below).
2. Load the bitmap for the alternate button image.
3. Use TB_ADDBITMAP to add the alternate image to the image list (be sure to store its image index).
4. Get the image index for the button in the toolbar whose image you want to change, using TB_GETBUTTONINFO. Be sure to store its image index as well.

In this demo the third button changes when you click on it.
To change a button's image, send the TB_CHANGEBITMAP message with the image index of the image you want to show. It's that simple!

Notes:
There are two numbers associated with each button in a toolbar:
o The command ID is the ID you associate with a button (using the TB_ADDBUTTONS message, where the command IDs are in the TBBUTTON structure passed in the message);
o The image index of the button's image, which is the zero-based index into the image list that Windows creates for the toolbar. The index #s don't change; new images are added to the end of the list. And when you create a toolbar from a bitmap that contains multiple buttons (as the 5 here), each button image becomes a separate image in the image list, identified by its image index. So the toolbar bitmap contains images 0 through 4.

You need both of these numbers to change the image. The image index doesn't change: in my demo program, there are 5 toolbar buttons, plus the "new" button image (the alternate image), so the image indices are

0, 1, 2, 3, 4, 5

with 5 being the "new" (alternate) one.

What the demo does is swap images 2 and 5 for the 3rd button, using TB_CHANGEBITMAP. In other words, for command ID 2, it shows either image index 2 or 5. Or to put it another way, this message assigns a different image (using its image index) to a certain button using its command ID.

Here's my recipe for setting up the toolbar in the first place:

1. Create the toolbar window using CreateWindowEx().
2. Set the size of the TBUTTON structure using TB_BUTTONSTRUCTSIZE.
3. Set the size of the bitmap (width & height) using TB_SETBITMAPSIZE.
4. Add the bitmap to the toolbar using TB_ADDBITMAP. (But see note below.)
5. Create the buttons in the toolbar using TB_ADDBUTTONS, passing an array of TBBUTTON structures which contain the button command IDs and other info.
6. Set the button size using TB_SETBUTTONSIZE.
7. Set up tooltips using TB_SETEXTENDEDSTYLE. NOTE: You should do this even if you don't use tooltips (the little text cues that pop up when you mouse over the toolbar buttons), since the toolbar will be slightly malformed if you don't. You can simply omit the tooltip text (in the TBBUTTON structure as I've done in this demo) and it'll work fine.

Note on loading bitmaps:
There are at least 3 ways to load bitmaps into a toolbar:
1. Create separate BMPs and load each separately in your code.
2. Load all the BMPs using a resource file with the resource editor, accessing them by their resource ID.

I've chosen to use a third method which I prefer. I don't deal with BMP files at all, at least not directly. What I do is convert all my bitmaps to data (DB statements) in include files, using Hutch's handy-dandy bin2db utility that's part of the MASM package. (See the two files in the .zip.)

Then I use a little routine in my code, GetBMPdata(), to "load" the bitmap from that data and give me a handle to the bitmap. (Thanks again to "fearless" of this forum for providing that trick.) I do this because I'm not a big fan of using resource files and the resource compiler.

Of course, you can load the bitmaps however you choose, and all this will work just fine.
Assembly language programming should be fun. That's why I do it.

zedd151

Seems to work as expected, and  without any issues.  :thumbsup:

But why would anyone need to change toolbar buttons dynamically? That part I don't understand. At least I cannot think of any reasons to do that.
¯\_(ツ)_/¯   :azn:

'As we don't do "requests", show us your code first.'  -  hutch—

NoCforMe

Quote from: zedd151 on March 26, 2025, 03:16:46 PMSeems to work as expected, and  without any issues.  :thumbsup:

But why would anyone need to change toolbar buttons dynamically? That part I don't understand. At least I cannot think of any reasons to do that.

My reason for doing this is to have a toolbar button that acts as a toggle between two states, enabled and disabled.
This eliminates the need for a separate indicator of what state the button is in.
Try the attached demo to see what I mean; click the 3rd button.
You can see the two images are the same except for the "X" over the "disabled" one.
Assembly language programming should be fun. That's why I do it.

zedd151

Ok. That makes sense, I hadn't thought about that.  :biggrin:
I'll look at that last attachment when I get back inside.
¯\_(ツ)_/¯   :azn:

'As we don't do "requests", show us your code first.'  -  hutch—

guga

Tks, NoCForme.

Good work.  :thumbsup:  :thumbsup:

The simplified version of GetBMPdata from fearless is really good.
Coding in Assembly requires a mix of:
80% of brain, passion, intuition, creativity
10% of programming skills
10% of alcoholic levels in your blood.

My Code Sites:
http://rosasm.freeforums.org
http://winasm.tripod.com

guga

Quote from: zedd151 on March 26, 2025, 03:16:46 PMSeems to work as expected, and  without any issues.  :thumbsup:

But why would anyone need to change toolbar buttons dynamically? That part I don't understand. At least I cannot think of any reasons to do that.

It´s needed to change the state of the buttons. I gave a try with something similar years ago when i was trying to fix old bugs in RosAsm. His version of loading the image to the buttons seems easier and way less complicated. I´ll give a try on his technique once i succeed to fix a couple of more things in RosAsm before starting to change the appearance of the interface as i did here:


Coding in Assembly requires a mix of:
80% of brain, passion, intuition, creativity
10% of programming skills
10% of alcoholic levels in your blood.

My Code Sites:
http://rosasm.freeforums.org
http://winasm.tripod.com

zedd151

Quote from: NoCforMe on March 26, 2025, 03:50:19 PMTry the attached demo to see what I mean; click the 3rd button.
You can see the two images are the same except for the "X" over the "disabled" one.
Works as advertised... Now I C.
¯\_(ツ)_/¯   :azn:

'As we don't do "requests", show us your code first.'  -  hutch—

TimoVJL

So more visible than with TB_ENABLEBUTTON message ?
May the source be with you


zedd151

#9
Quote from: TimoVJL on March 26, 2025, 08:32:22 PMSo more visible than with TB_ENABLEBUTTON message ?
Just as visible I would imagine.  :biggrin:

Do you not like NoCforMe's approach? It works...

Quite possible that he did not know about TB_ENABLEBUTTON (I didn't, or if I had known, I had forgotten),  or he simply wanted to experiment with the 'dynamic button image' approach?

That's the fun of experimenting. There are frequently several different ways to achieve the same desired outcome.
We don't always have to follow the prescribed 'norms'.  :cool:

I prefer 'outside the box' thinking in certain instances.

¯\_(ツ)_/¯   :azn:

'As we don't do "requests", show us your code first.'  -  hutch—

TimoVJL

OK, there is different idea for button bitmaps, that can change bitmap during usage.
Like operational cycles / phases, when button purpose varies.
May the source be with you

NoCforMe

Quote from: TimoVJL on March 26, 2025, 08:32:22 PMSo more visible than with TB_ENABLEBUTTON message ?
That message has a completely different purpose from mine:
It simply enables or disables an existing button, without changing the button's bitmap image. (Well, it'll gray the button out if it's disabled.)
Mine actually substitutes a different bitmap image.
So not the same thing at all.
Assembly language programming should be fun. That's why I do it.

NoCforMe

Quote from: TimoVJL on March 27, 2025, 02:36:11 AMOK, there is different idea for button bitmaps, that can change bitmap during usage.
Like operational cycles / phases, when button purpose varies.

Yes, exactly.
Which brings up a caveat for this usage:
When you start changing button images, you now have a "modal" application, meaning that the appearance or functionality changes depending on which "mode" it's in.
Which can be a really bad thing (for the user), so it needs to be carefully considered before implementing it.
Assembly language programming should be fun. That's why I do it.

zedd151

Quote from: NoCforMe on March 27, 2025, 11:27:36 AM
Quote from: TimoVJL on March 26, 2025, 08:32:22 PMSo more visible than with TB_ENABLEBUTTON message ?
That message has a completely different purpose from mine:
It simply enables or disables an existing button, without changing the button's bitmap image. (Well, it'll gray the button out if it's disabled.)
Mine actually substitutes a different bitmap image.
So not the same thing at all.
Lol.
I missed the point entirely.  :biggrin:

You want a certain function disabled or changed, and use the button image to display the state of the function. Enabled or disabled, (or other?)

Now if the button itself was disabled once used, along with disabling the function...
How would one re-enable the function.  :joking:

That is what I get for making a reply before my morning coffee.  :mrgreen:
¯\_(ツ)_/¯   :azn:

'As we don't do "requests", show us your code first.'  -  hutch—

NoCforMe

Quote from: zedd151 on March 27, 2025, 12:04:43 PMYou want a certain function disabled or changed, and use the button image to display the state of the function. Enabled or disabled, (or other?)

Now if the button itself was disabled once used, along with disabling the function...
How would one re-enable the function.  :joking:

Wellll, in that case you'd be navigating that proverbial body of water known as Schitt's Creek ...

So of course you'd never use TB_ENABLEBUTTON here. Unless you really wanted to mess with the poor user.
Assembly language programming should be fun. That's why I do it.