The MASM Forum
General => The Workshop => Topic started by: zedd151 on September 15, 2022, 02:04:05 AM
-
I found this interesting...
While working on a current project, I needed a couple radio buttons and a checkbox in the GUI.
The background of the GUI is white. Using WM_CTLCOLORBTN had no effect on the color of the two types of buttons. After some experimentation I found that using WM_CTLCOLORSTATIC instead works for these style of BUTTONs. I guess even though they are both "BUTTON" class, underneath they are merely glorified STATIC controls.
-
Z,
It only effects the button border colour. If you set the colour to the same as the background, you get rid of the ugly line border.
-
@ hutch-- see the attachment, it explains everything. :biggrin:
Heres a snippet
.elseif uMsg == WM_CTLCOLORBTN ;; has zero effect
mov eax, lParam
.if eax == hRadio1 || eax == hCheck1
invoke GetStockObject, WHITE_BRUSH
return eax
.endif
.elseif uMsg == WM_CTLCOLORSTATIC ;; works
mov eax, lParam
.if eax == hRadio2 || eax == hCheck2
invoke GetStockObject, WHITE_BRUSH
return eax
.endif
-
I don't need to, I have been using it for 30 years. :tongue:
-
Not pushbuttons, which I think you are referring to; radio buttons and check boxes. :biggrin:
-
Same comment, 30 years of practice here. If you use a manifest, radio buttons and check boxes look terrible but there is a trick that works OK, use only the square in a check box and the circle in a radio button, do the text for either with a static control where you can set the background colour. The side effect is you can only click on either the square or circle.
-
Same comment here as well; I don't doubt your experience. Using WM_CTLCOLORSTATIC works as in the attached example in my first post here, without needing to use separate controls. I found it interesting that a BUTTON class radio button and checkbox would respond to WM_CTLCOLORSTATIC message rather than WM_CTLCOLORBTN. Yes, it uses manifest. And works as described. I just thought that someone may find this useful.
-
Attached a slightly changed (changed controls font) and commented version; the places of interest are commented.
And an image displayed here, to disply what the code demonstrates; that check boxes and radio buttons DO NOT receive the WM_CTLCOLORBTN message, but rather the WM_CTLCOLORSTATIC message; WM_CTLCOLORBTN is not sent for these controls; I was surprised to find that since both controls are "BUTTON" class controls, not "STATIC", hence the reason for this topic.
hutch, there was no reason for the dismissive attitude. You obviously did not understand what I was demonstrating since you refused to even look at the example. This image is for you to clearly show what I tried to explain in my first post. Neither of the 2 controls using WM_CTLCOLORSTATIC to set the color are ugly, nor do they need a 'trick' to display properly. Sorry but you are wrong in this instance. Even old dogs CAN learn new tricks, even if they are set in their ways. I learn new tricks all the time. Also the WM_CTLCOLORBTN message is not sent for these controls as verified by examining with my good friend Ollie; which explains why trying to set the color there has zero effect on the control whatsoever. :tongue:
-
ControlSpy may help looking messages
Control Spy 2.0 (https://www.microsoft.com/en-us/download/details.aspx?id=4635)
-
ControlSpy may help looking messages
Nice litte tool for tracking unknown messages being sent but in this case I already know what message I'm looking for, as seen in ollydbg with a breakpoint set on the two messages in question. but thanks for the link to that tool, I'll add it to my toolbox. :cool:
-
Attached a slightly modified version that shows you which messages you get. A single click on one of the buttons triggers up to 7 WM_CTLCOLORSTATIC messages :rolleyes:
-
Attached a slightly modified version that shows you which messages you get. A single click on one of the buttons triggers up to 7 WM_CTLCOLORSTATIC messages :rolleyes:
Exactly the point I was making; thanks for the confirmation though. (Yes, WM_CTLCOLORSTATIC is called --- NOT WM_CTLCOLORBTN which is never called thats the point I was making. :biggrin: ...which a normal person would expect from a BUTTON class control.) Is that clear enough now? :mrgreen:
So why the eye roll? :tongue:
I think you guys just like arguing for the sake of the argument. Even with a clearly commented code example, you still get it wrong.
;; small demo, showing that WM_CTLCOLORBTN is not sent for radio buttons
;; or check boxes.
.elseif uMsg == WM_CTLCOLORBTN ;; this message is never sent! :P
mov eax, lParam ;; so this code never executes.
.if eax == hRadio1 || eax == hCheck1 ;; if handle = hRadio1 or hCheck1
invoke GetStockObject, WHITE_BRUSH
return eax
.endif
;; BUT WM_CTLCOLORSTATIC message is sent. This can be checked in a debugger.
.elseif uMsg == WM_CTLCOLORSTATIC ;; but, THIS message is sent. :D
mov eax, lParam
.if eax == hRadio2 || eax == hCheck2 ;; if handle = hRadio2 or hCheck2
invoke GetStockObject, WHITE_BRUSH
return eax
.endif
Now its my turn... :rolleyes:
-
First of all, Swordfish: Good stuff. This is why we come here, to get info like this.
My recent experience with trying to render buttons nicely is related, even though it doesn't involve WM_CTLCOLORSTATIC. My situation is a little different, which explains why I had to find a different solution. The situation: I have a bunch of buttons that are children of a static "container" control. They were being rendered like the top picture. Ugly, with an unwanted white border around them. I was responding to WM_CTLCOLORBTN and returning the background color brush, which got me partway there, but still the white border.
Long story short, I found I had to look for WM_NOTIFY: lParam->NMHDR.code = NM_CUSTOMDRAW && lParam->NMCUSTOMDRAW.dwDrawStage = CDDS_PREERASE (ain't that a mouthful!), and when that occurred do a FillRect() of the background color on the RECT contained in the NMCUSTOMDRAW structure. Which gave me the nice 2nd picture below.
After reading this thread I tried using WM_CTLCOLORSTATIC to try to accomplish the same thing (returning the background color brush to try to fill in the white border), but it didn't work. But still, this is good info.
BTW, I'm pretty sure that the WM_CTLCOLORSTATIC notification doesn't come because the button control actually creates a static, but just as a notification to fill in that part of the control.
-
BTW, I'm pretty sure that the WM_CTLCOLORSTATIC notification doesn't come because the button control actually creates a static, but just as a notification to fill in that part of the control.
Still radio buttons and check boxes still seem like glorified static controls, sending WM_CTLCOLORSTATIC messages instead of the expected WM_CTLCOLORBTN.
-
After my last reply to your post, I started thinking of the ramifications of this......triggers up to 7 WM_CTLCOLORSTATIC messages
That's actually a good thing. Tells me that I should not obtain the brush handle there, but just use a handle obtained during WM_CREATE. So in light of this, thanks for this info. I would have missed that. No need to keep calling GetStockObject repeatedly. :biggrin:
-
So why the eye roll? :tongue:
Because I think that 7 x WM_CTLCOLORSTATIC is really an overkill, and very inefficient. But that's not your fault, it's Windows...
-
After my last reply to your post, I started thinking of the ramifications of this......triggers up to 7 WM_CTLCOLORSTATIC messages
That's actually a good thing. Tells me that I should not obtain the brush handle there, but just use a handle obtained during WM_CREATE. So in light of this, thanks for this info. I would have missed that. No need to keep calling GetStockObject repeatedly. :biggrin:
Why not do as I do, and just create the brush once--really anywhere in your code, the mainline routine, WM_CREATE, whereever--and then just use it. And if you use GetStockObject(), you don't even need to delete it when you're done. Just make the handle global. (Assuming, of course, that you know the color of the brush beforehand.)
-
Because I think that 7 x WM_CTLCOLORSTATIC is really an overkill, and very inefficient. But that's not your fault, it's Windows...
ok. I misinterpretted then. I thought you were suggesting I shouldn't be using WM_CTLCOLORSTATIC, or that you thought I was suggesting that it wasn't called. I'll still use it since it does work for the intended purpose and doesn't seem to cause any issues.
-
and just create the brush once
Yeah, that was an oversight on my part. I just copied the code for the two messages, and didn't think about it getting called repeatedly in each message sent until jj mentioned that the message gets sent xxx amount of times.
edit to add:
Fixed version below. GetStockObject now called only once :tongue: