tags:

views:

49

answers:

4

I have a window with a button that paints the entire window red when clicked, but my code paints the whole window, even the button. When I resize the window or cause the part of the window where the button is to repaint, the button will return. I've only been able to paint the button a solid color after painting the window, but that only makes it look like a square with nothing in it.

So how do I paint the button its default color?

//WinMain 
hmain = CreateWindowEx (0, L"Window", L"Window", WS_OVERLAPPEDWINDOW, 0, 0, 200, 200,
    NULL, NULL, hinstance, NULL);

HWND hwnd2 = CreateWindowEx (0, L"Button", L"Red", WS_CHILD | BS_PUSHBUTTON, 0, 0, 50, 50,
    hmain, (HMENU) redbtt, hinstance, NULL);
//Winmain

//WndProc
COLORREF red = RGB (255, 0, 0);
HBRUSH redbrush = CreateSolidBrush (red);

switch (msg) {
    case WM_COMMAND: {
        if (LOWORD (wparam) == redbtt) {
            color = 'r';
            RECT rect;
            GetClientRect (hmain, &rect);
            HDC hdc = GetDC (hmain);
            FillRect (hdc, &rect, redbrush);
            ReleaseDC (hmain, hdc);

            /*GetClientRect ((HWND) lparam, &rect);
            hdc = GetDC ((HWND) lparam);
            COLORREF color = GetBkColor (hdc);
            HBRUSH brush = CreateSolidBrush (color);
            FillRect (hdc, &rect, brush);
            ReleaseDC ((HWND) lparam, hdc);*/
        }

        break;
                     }
    case WM_PAINT: {
        HBRUSH brush;

        if (color == ' ') {
            brush = (HBRUSH) (COLOR_WINDOW + 1);
        } else if (color == 'r') {
            brush = redbrush;
        }

        PAINTSTRUCT ps;
        HDC hdc = BeginPaint (hmain, &ps);
        FillRect (hdc, &ps.rcPaint, brush);
        EndPaint (hmain, &ps);
        break;
                   }
//WndProc
+1  A: 

It's been a while since I've done Win32, but it seems to me your painting stuff would be better as a WM_ERASEBKGND, since that seems to be what you're doing. Have you tried it there? (You'll have to look and see, but I'm not sure if BeginPaint is appropriate for WM_ERASEBKGND)

Also, you should be calling DeleteObject on the result of the CreateSolidBrush. I'd also wait until inside the painting stuff to allocate it - I wouldn't allocate the brush on every message your window got.

Thanatos
A: 

WM_PAINT is the time for drawing something on top of the background. If you want the window to be solid red and not flash between default background and reg then you probably want to use WM_ERASEBKGND.

You might also consider clipping the rectangle so that you don't paint under solid controls.

Finally you can always invalidate or send a WM_PAINT to controls you want to force to redraw.

Greg Domjan
+1  A: 

It is because you didn't turn on the WS_CLIPCHILDREN style for the main window. Fix:

hmain = CreateWindowEx (0, L"Window", L"Window", 
          WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN, 0, 0, 200, 200,
          NULL, NULL, hinstance, NULL);

The 'color' variable is a hack, avoid this in real code. You're leaking the brush btw.

Hans Passant
What does that mean? It's just a char determines what color should be painted in WM_PAINT.
TreeTree
It is a global variable. Have you heard about the evil of global variables yet? Particularly unkind to an event-driven programming style that Windows enforces. "color" is strongly associated to the window, not the global state of your program and all the *other* windows it creates.
Hans Passant
A: 
  1. You should set the WS_CLIPCHILDREN style to your window. This way the are of the button will be automatically excluded from the drawing region, hence your button won't become "overwritten".
  2. You can use the InvalidateRect, `function to achieve the needed efect.
valdo