user4344762
user4344762

Reputation:

BeginPaint() not erasing the background

BeginPaint() documentation says:

If the window's class has a background brush, BeginPaint uses that brush to erase the background of the update region before returning.

I have set the brush like this:

wc.hbrBackground = (HBRUSH)(COLOR_BTNFACE+1);

I have drawn a bitmap on my Window, and then I asked for a redraw using the following code:

RedrawWindow(hWnd, 0, 0, RDW_INVALIDATE | RDW_UPDATENOW);

and I have this code in WM_PAINT:

case WM_PAINT:
    {
        PAINTSTRUCT ps;
        HDC hdc = BeginPaint(hWnd, &ps);

        EndPaint(hWnd, &ps);
    }
    break;

So I expected that BeginPaint() will erase the bitmap, but the bitmap remained on the Window!

I am using Windows 7.

Upvotes: 1

Views: 1514

Answers (1)

Jonathan Potter
Jonathan Potter

Reputation: 37132

(Writing this as an answer because the explanation is too long for a comment).

Painting of the client area can be done in two places in the standard Windows model:

WM_ERASEBKGND nominally handles erasing the background. WM_PAINT nominally handles drawing things over the background.

If you pass WM_ERASEBKGND through to DefWindowProc, it will paint the background using the class brush. You have two choices if you want to handle WM_ERASEBKGND yourself:

  • You can erase the background yourself, and return 1 (or any non-zero value)
  • You can do no erasing, and return 0

If you implement the latter option, when you later get a WM_PAINT message and call BeginPaint, the fErase flag of the PAINTSTRUCT will be set to TRUE, indicating that the background is still marked for erasure.

The BeginPaint function itself doesn't do any painting at all, all it does is give you a DC that you can paint into. When you call EndPaint the region that was previously marked as dirty is "deemed" to have been painted (and erased) and will no longer be marked as dirty.

The division of painting in background erasure and foreground painting is (in my opinion at least) a remnant of the 16 bit world where painting was an expensive operation. If foreground painting also erases the background (e.g. you are drawing a solid block of colour or a solid image) then erasing the background as a separate step is a waste of time, and will often lead to visible flicker. So depending on your application you may wish to ignore the "erase background" step altogether - return 0 from WM_ERASEBKGND and in WM_PAINT paint the "background and foreground" in a single step.

Upvotes: 4

Related Questions