WM_ERASEBKGND not erasing drawing

I want to draw a moving shape, either on WM_MOUSEMOVE or in a Timer. But the old shapes are not erased when I use the following handler:

1
2
case WM_ERASEBKGND:
    return 1;


I need to avoid flickering in my program, so I need WM_ERASEBKGND. The drawing is 'refreshed' in a WM_PAINT handler. The WM_PAINT handler is triggered by a RedrawWindow(...) call. What should I do to use WM_ERASEBKGND and to erase the old shapes at the same time?
Try using InvalidateRect (with last param, bErase, TRUE) instead of RedrawWindow

 
InvalidateRect(hwnd, NULL, TRUE);

Last edited on
Using InvalidateRect erases the old shapes only when I use:
1
2
case WM_ERASEBKGND:
      break;

But the flickering is now even heavier. Maybe I need to use double buffering. But how to implement that in my situation?
I don't know if it can be done properly with the windows message loop. You could try SDL.

But if you want to try something, get rid of WM_ERASEBKGND entirely and in the WM_PAINT event, draw on a separate bitmap and then bitblt the whole thing to the window. I can't test this, but something like the following:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
{
    HDC mem_dc = CreateCompatibleDC(hdc);
    HBITMAP mem_bm = CreateCompatibleBitmap(hdc, width, height);
    SelectObject(mem_dc, mem_bm );

    // Draw to the mem_dc.
    // ...

    // then:
    BitBlt(hdc, 0, 0, width, height, mem_dc, 0, 0, SRCCOPY);

    DeleteObject(mem_bm)
    DeleteDC(mem_dc);
}

I am trying the double buffering, but it won't let me draw on the mem_dc (it is not shown), whereas I can draw on the hdc. How to draw using the mem_dc?
Can you show us the code, otherwise it's impossible to see if you do sth. wrong.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
case WM_PAINT: {
hdc = BeginPaint(hwnd, &ps);
hdcBackbuff = CreateCompatibleDC(hdc);
bitmap = CreateCompatibleBitmap(hdc, 1000, 1000);
SelectObject(hdcBackbuff, bitmap);

MoveToEx(hdcBackbuff, 160, 300);
LineTo(hdcBackbuff, 1000, 300);
MoveToEx(hdc, 160, 100);
LineTo(hdc, 1000, 100);

hdc = GetDC(hwnd);
ReleaseDC(hwnd, hdc);
BitBlt(hdc, 0, 0, 1000, 1000, hdcBackbuff, 0, 0, SRCCOPY);
DeleteDC(hdcBackbuff);
DeleteObject(bitmap);
EndPaint(hwnd, &ps);

break;
}
Have a closer look at lines 12-14.
First you overwrite hdc, then you release it and then you want to draw on it.

Remove the lines 12-13 and see what you get.
I have put those lines 12-13 in to avoid a black screen, so now the question is how to get a white screen with a drawing using hdcBackbuff.
You have to draw it yourself using the FillRect function.
https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-fillrect
In whice place should I put the

 
FillRect(hdc, &ps.rcPaint, (HBRUSH)(COLOR_WINDOW+1));


then to show at least the drawing of the hdc?
Also, how to show the drawing of the hdcBackbuff?
Your code should look like this:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
  case WM_PAINT:
  {
    hdc = BeginPaint(hWnd, &ps);
    hdcBackbuff = CreateCompatibleDC(hdc);
    bitmap = CreateCompatibleBitmap(hdc, 1000, 1000);
    SelectObject(hdcBackbuff, bitmap);
    FillRect(hdcBackbuff, &ps.rcPaint, (HBRUSH)GetStockObject(WHITE_BRUSH));
    MoveToEx(hdcBackbuff, 160, 300, NULL);
    LineTo(hdcBackbuff, 500, 300);
    MoveToEx(hdcBackbuff, 160, 100, NULL);
    LineTo(hdcBackbuff, 700, 100);
    BitBlt(hdc, 0, 0, 1000, 1000, hdcBackbuff, 0, 0, SRCCOPY);
    DeleteDC(hdcBackbuff);
    DeleteObject(bitmap);
    EndPaint(hWnd, &ps);
    break;
   }
Thanks! In combination with WM_ERASEBKGND and return 1 it does not flicker anymore.
Topic archived. No new replies allowed.