Click to See Complete Forum and Search --> : Background color of a child window


JensE
September 22nd, 2003, 03:43 AM
Hi!

I've got a problem in an application with painting the background of a child window. Because child windows have no WNDCLASSEX structure applied to them, I cannot change the background brush.
So I tried the SetBkColor function, but nothing happened.
I even tried do create a bitmap in the DC of that window, but the funtions I used to fill the bitmap with pixels (I tried SetPixel, SetBitmapBits, and the array you can pass as a parameter to the CreateBitmap function with color data [yes: I selected the Bitmap]) didn't show anything in the window. I suppose there must be an easy way to paint the background of a window in a homogeneous color. What about SetBkColor and its usage?
Is there a way to use WM_PAINT with the child window or WM_PRINTCLIENT, WM_ERASEBKND ans so on, and if so, how to use this messages?

JasonD
September 22nd, 2003, 10:05 AM
To process these messages with your own windows procedure, instead of the windows procedure that is being used by the child window, you can subclass (it's normally called subclassing). Basically, you get Windows to call your own windows procedure first, and you handle the messages you wish, and pass the rest to the original window procedure. Use SetWindowLong() with GWL_WNDPROC, to set a new window procedure (and it will return the old one). Within your window procedure for the child window, use CallWindowProc() to call the old one after you are finished handling the messages you wish. You should search the net for a more detailed explanation, or let us know specifically what you need extra help with.

filthy_mcnasty
September 22nd, 2003, 05:42 PM
subclassing and handling a wm_paint message is certainly one way to do it but you can do wm_paint as follows

PAINTSTRUCT ps;
HDC hDC;

WM_PAINT:
hDC = BeginPaint(ChildHandleHere, &ps);

in the parent's window procedure and paint (almost) like normal.

that said there are still easier ways to go about doing this.

seeing as how you're in the winapi forum i'm assuming you're using all win32 in which case you need to simply process the

WM_CTLCOLORDIALOG
WM_CTLCOLOREDIT
WM_CTLCOLORLISTBOX
WM_CTLCOLORSTATIC

etc etc

messages in the parents window procedure.

case WM_CTLCOLORLISTBOX:
SetTextColor((HDC)wParam, Green);
SetBkColor((HDC)wParam, Black);
return (LRESULT)hbg;


the LPARAM here (not used in this example) is the handle to the child window so you can distinguish between them and color accordingly.

where Green and Black are COLORREFS and hbg is the handle to a brush (only create the brush once! not in every call to this message!)

this is *in my opinion* by far the most simple approach, just make sure you handle creation/deleting of resources properly.

if you're using MFC then handle WM_CTLCOLOR.

JensE
September 23rd, 2003, 06:59 AM
@filthy_mcnasty: I tried to use WM_PAINT and so on, but the result was that all the child windows were not visible! The whole client area of the window was just gray (what did I do wrong?).

Thanx for response, gonna try it soon.

filthy_mcnasty
September 23rd, 2003, 10:25 AM
it's hard to say, there are many things that could have been wrong. post your code but definately go with the color messages instead.

JasonD
September 23rd, 2003, 01:11 PM
Originally posted by filthy_mcnasty ...but definately go with the color messages instead. I agree.

I guess my post was just a response to the last question you had: "Is there a way to use WM_PAINT with the child window or WM_PRINTCLIENT, WM_ERASEBKND ans so on, and if so, how to use this messages?" Sorry for being incomplete.

JensE
September 25th, 2003, 07:05 AM
Thank you for your help.

For users having the same problem let me resume:

If you want to paint the background of a window in a homogeneous color, use the WM_CTLCOLORxxxxx messages, replace xxxxx by STATIC for static window classes, LISTBOX for list boxes and so on (search MSDN), then you pick out the window you want to repaint (which handle is delivered by the lParam) and return the brush containing the color you want. Here is an example code:

HBRUSH hBrush; // global

hBrush CreateSolidBrush(0x00FFFFFF); // Create white brush (not
// within the window proc!)

WM_CTLCOLORSTATIC: // within the main window proc
if ((HWND) lParam == hWindow) // Paint this window's back-
return hBrush; // ground white

// don't return 0, cause deactivated edit controls
// may be painted white then, just don't return anything here
break;


I also found out that the RedrawWindow() function also sends WM_CTLCOLORxxxx messages to the main window proc, if you specify the RDW_INTERNALPAINT flag or you simply send the message with SendMessage().


Bye Jens.