Hey all, im trying to finish some earlier projects. One is a custom control...

Its nearly finished, and when i wrote it i tested it for system color changes and it worked fine. My proceedure picked up the WM_SYSCOLORCHANGE message and all was well.

Then when i acutally added the control into another project, and created an instance of its class.. it would work on creation, but failed to recognize any color changes while the program is running.

I re-looked up the info on the MSDN, and realized that WM_SYSCOLORCHANGE is sent to all *top* level windows. Since it was a child control, then obviously this is why it is not recieving this.

However, i got wondering... I compared my control's CLASS and STYLE flags to the 'Button' control defualt flags (with SpyWindow). I found out that they are 100% the same. Even they both register as a child window of the main parent window.

The catch is, a normal Button *will* recieve this WM_COLORCHANGE message. Even tho its a child (like my control is). So i no longer understand how this *really* works. By the MSDN info, this should not happen, at all.

Can anyone tell me how to make the OS send WM_SYSCOLORCHANGE to a custom control window, that is instanciated as a child of another window ~ just like normal windows controls???

After all, we dont need to process default window controls for this case ~ Hutch's prostart doesnt even add this message handler in its template, yet all basic child controls still get this message... :confused:

Anywho.. thanx alot for any advice..
Posted on 2002-04-15 02:02:42 by NaN

The approach I use is to redraw the control from the WM_SYSCOLORCHANGE that is processed by the main window. What you don't know with the operating system supplied components is if the OS sends a message to the control to redraw after the system color has been changed.

I think you could trigger the redraw by using "InvalidateRect" on the client area of the control and in the redraw it should pick up the new color.


Posted on 2002-04-15 07:10:01 by hutch--
Ya i realize this, thank you :)

I could also just forward the message along to all 'custom' child windows. But i think its dumb that this has to be outside the encapsulation im trying to achieve with the custom control.

I dont like the idea of finishing up the control and having to put restrictions on it like "oh ya, and dont forget to process the WM_SYSCOLORCHANGE message for this control in your main program"... :rolleyes:

I was hoping there would be a "special" list with an API i dont know about, that would allow my class to be inserted on its queue, and windows would send it these messages as well as its normal controls. :(

Again thanx for your sugestions...
Posted on 2002-04-15 10:36:47 by NaN
Originally Written by Umbongo
(apologies for the private message, I don't seem to be able to post public from work :-( )


I'm not sure if it will help, but consider this:-

Each time a button is re-drawn then it looks up the system colour it should be. So when WM_SYSCOLORCHANGE is issued the top window gets it, and forces a re-paint of all the child windows. This was the buttons get their new colours.

If you custom control looks up it's colour at the start and keeps it in a variable, then the re-pain will not make it change colour.

You'll have to look up the colour each time you paint, otherwise you'll not get the message.


Im posting this, as i think (havent tested it yet) it directly applies to my problem at hand. (And for future seaching sake, i thought credit should be properly made for the solution).

My 'control' processes the WM_SYSCOLORCHANGE message, and when it does, rebuilds all my pens and brushes for GDI work by relooking up the new colors.

As a toplevel window this worked everytime. But when applied as a contorl (and thus a child window), it never recieves the WM_SYSCOLORCHANGE message (this is what frustrated me).

However, Umbongo points out, that im thinking in the wrong direction here... the top level also forces a re-paint, which will then filter out to all child windows (including my control). Since i only process for new brushes/pens in a separate handler of WM_SYSCOLORCHANGE, the repaint would use the old colors (as im seeing!).

This is the best explaination I can see at the moment and make good sense to me (as well maybe i missunderstood Hutch's suggestion of InvalidateRect ~ as it would also follow this line of thought).. I will have to change the structure a bit in my control code, but i think this will work..

Only down side is it will be calling for pens and brushes on every paint message.. I dunno how much overhead this will actually cause, but i hope they are fast API's :)

Thanx alot Umbongo and Hutch!
Posted on 2002-04-15 10:57:28 by NaN
To finalize this discussion, it now works!

Basic outline of the aproach was:

- Build needed pens and brushes, and store originals..
- Set 'SetColor' variable to == invoke GetSysColor, COLOR_BTNFACE
- Draw bitmap images for BitBlt's

- Totaly removed from intended child control

.if( SetColor != invoke GetSysColor)
- Rebuild new pens and brushes
- destroy previous pens and burshes
- Redraw bitmap images for BitBlt's

- Do rest of WM_PAINT as always

Thanx alot Umbongo and Hutch, i dont think i would have seen this on my own (its obvious now however ;) )
Posted on 2002-04-15 11:40:04 by NaN
aah back home now :-)

Posted on 2002-04-15 15:06:08 by umbongo