[RESOLVED] Double Buffer (CreateCompatibleDC) black/white screen flashing
I am trying to avoid screen blinking so I tried this code:
hDC = BeginPaint(hwnd, &ps);
HDC memoryHDC = CreateCompatibleDC(hDC);
HBITMAP hMemoryBmp = CreateCompatibleBitmap(hDC, 700, 700);
HBITMAP hOldBmp = (HBITMAP)SelectObject(memoryHDC, hMemoryBmp);
//
//
// painting
//
//
BitBlt(hDC, 0, 0, 700, 700, memoryHDC, 0, 0, SRCCOPY);
SelectObject(memoryHDC, hOldBmp);
DeleteObject(hMemoryBmp);
DeleteDC(memoryHDC);
EndPaint(hwnd, &ps);
But what I am getting is a black sreen with flashing white background, painting works, but with this side effect only.
[707 byte] By [
dentiol] at [2007-11-20 11:46:34]

# 1 Re: [RESOLVED] Double Buffer (CreateCompatibleDC) black/white screen flashing
I am trying to avoid screen blinking...How do you handle WM_ERASEBKGND message?
# 2 Re: [RESOLVED] Double Buffer (CreateCompatibleDC) black/white screen flashing
do you mean the screen was flashing before you tried this? or only afterwards?
when you create the compatible bitmap it will be initialised to zero, so maybe that is your black frame? why would you do this for the WM_PAINT message anyway?
when i put this code into WM_PAINT:
case WM_PAINT :
{
PAINTSTRUCT ps;
HDC hDC = BeginPaint(hWnd, &ps);
HDC memoryHDC = CreateCompatibleDC(hDC);
HBITMAP hMemoryBmp = CreateCompatibleBitmap(hDC, 700, 700);
HBITMAP hOldBmp = (HBITMAP)SelectObject(memoryHDC, hMemoryBmp);
BitBlt(hDC, 0, 0, 700, 700, memoryHDC, 0, 0, SRCCOPY);
SelectObject(memoryHDC, hOldBmp);
DeleteObject(hMemoryBmp);
DeleteDC(memoryHDC);
EndPaint(hWnd, &ps);
}
break;i just get a black client area with no flicker.
maybe it is to do with WM_ERASEBKGND
# 3 Re: [RESOLVED] Double Buffer (CreateCompatibleDC) black/white screen flashing
Indeed, if you don't handle the erase background (turning into a 'do nothing'), then turn your attention erasing the bitmap when appropriate, you WILL have flicker (really bad flicker).
JVene at 2007-11-9 13:34:58 >

# 4 Re: [RESOLVED] Double Buffer (CreateCompatibleDC) black/white screen flashing
I added WM_ERASEBKGND handling:
case WM_ERASEBKGND:
RECT rt;
GetUpdateRect(hwnd, &rt, FALSE);
hDC=GetDC(hwnd);
FillRect(hDC, &rt, (HBRUSH)CreateSolidBrush(RGB(255, 255, 255)));
ReleaseDC(hwnd, hDC);
break;
Screen is not flickering anymore, trouble is it remains black instead of being white.
# 5 Re: [RESOLVED] Double Buffer (CreateCompatibleDC) black/white screen flashing
Screen is not flickering anymore, trouble is it remains black instead of being white.
it is because your memory DC has a black bitmap in it.
to make it white:
LRESULT CALLBACK WndProc(HWND hwnd, UINT Msg, WPARAM wParam, LPARAM lParam)
{
HDC hDC;
switch (Msg)
{
case WM_DESTROY :
PostQuitMessage(WM_QUIT);
break;
case WM_ERASEBKGND:
RECT rt;
GetUpdateRect(hwnd, &rt, FALSE);
hDC=GetDC(hwnd);
FillRect(hDC, &rt, (HBRUSH)CreateSolidBrush(RGB(255, 255, 255)));
ReleaseDC(hwnd, hDC);
break;
case WM_PAINT :
{
PAINTSTRUCT ps;
hDC = BeginPaint(hwnd, &ps);
HDC memoryHDC = CreateCompatibleDC(hDC);
HBITMAP hMemoryBmp = CreateCompatibleBitmap(hDC, 700, 700);
HBITMAP hOldBmp = (HBITMAP)SelectObject(memoryHDC, hMemoryBmp);
// Create Bitmap Structure to fill the background of that window
LPBITMAPINFO lpbi = (LPBITMAPINFO)new BYTE[sizeof(BITMAPINFOHEADER)];
lpbi->bmiHeader.biBitCount = 32;
lpbi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
lpbi->bmiHeader.biWidth = 700;
lpbi->bmiHeader.biHeight = 700;
lpbi->bmiHeader.biPlanes = 1;
lpbi->bmiHeader.biCompression = BI_RGB;
lpbi->bmiHeader.biSizeImage = 0;
lpbi->bmiHeader.biXPelsPerMeter = 0;
lpbi->bmiHeader.biYPelsPerMeter = 0;
lpbi->bmiHeader.biClrUsed = 0;
lpbi->bmiHeader.biClrImportant = 0;
// Create Bit Array for the Bitmap
BYTE *bArray = new BYTE[4*700*700];
for(int i=0; i<700*700; i++)
{
bArray[(4*i)+0] = 0xff; //blue
bArray[(4*i)+1] = 0xff; //green
bArray[(4*i)+2] = 0xff; //red
bArray[(4*i)+3] = 0x00; //junk
}
// Set Bitmap Bits in Memory DC
SetDIBits(memoryHDC, hMemoryBmp, 0, 700, bArray, lpbi, DIB_RGB_COLORS);
delete[] lpbi;
delete[] bArray;
//DRAW STUFF ON MEMORY DC HERE
BitBlt(hDC, 0, 0, 700, 700, memoryHDC, 0, 0, SRCCOPY);
SelectObject(memoryHDC, hOldBmp);
DeleteObject(hMemoryBmp);
DeleteDC(memoryHDC);
EndPaint(hwnd, &ps);
}
break;
}
DeleteObject(hDC);
return DefWindowProc(hwnd, Msg, wParam, lParam);
}
# 6 Re: [RESOLVED] Double Buffer (CreateCompatibleDC) black/white screen flashing
Thank you, that solved problem completely !
# 7 Re: [RESOLVED] Double Buffer (CreateCompatibleDC) black/white screen flashing
Just a point to make...it may work now but.....
In all double buffering technique, the background erase should do nothing.
You're erasing the background in the example you posted, which is being erased so quickly at the moment that you don't see it, but you probably will when drawing becomes more complicated.
Part of the elimination of flicker is the elimination of the background erase, relying on the fact that the bitmap is a complete replacement of the viewing area, obviating the need for an on screen erasure.
(You erase the bitmap surface instead, as required - and in the PAINT cycle (or other bitmap drawing cycle), not in the background message response).
JVene at 2007-11-9 13:39:03 >

# 8 Re: [RESOLVED] Double Buffer (CreateCompatibleDC) black/white screen flashing
Just a point to make...it may work now but.....
In all double buffering technique, the background erase should do nothing.
You're erasing the background in the example you posted, which is being erased so quickly at the moment that you don't see it, but you probably will when drawing becomes more complicated.
Part of the elimination of flicker is the elimination of the background erase, relying on the fact that the bitmap is a complete replacement of the viewing area, obviating the need for an on screen erasure.
(You erase the bitmap surface instead, as required - and in the PAINT cycle (or other bitmap drawing cycle), not in the background message response).
that is a good point.
the erase background message is not required if you have a bitmap covering the whole client area of the window. you can set it to return 0 so that it does nothing even when the message is sent which is one way to eliminate flicker.
as far as i know the WM_ERASEBKGND message is mostly sent when you use InvalidateRgn(.., .., TRUE) or similar, or when you do things like resize the window.
if your bitmap does not cover the whole client area and you resize the window (with WM_ERASEBKGND disabled) then you get lots of trails of the window frame because the actual background is not erased.
this can be avoided by resizing the bitmap to cover the whole window when it is resized.
what i tend to do is have the 'background' window as the client area of the main window that just uses the DefWindowProc(). then if i want a bitmap somewhere i make a child window within the client area that is not resizeable and has its own window process to handle its own paint, mouse, etc.. messages.
# 9 Re: [RESOLVED] Double Buffer (CreateCompatibleDC) black/white screen flashing
Just a point to make...it may work now but.....
In all double buffering technique, the background erase should do nothing.
You're erasing the background in the example you posted, which is being erased so quickly at the moment that you don't see it, but you probably will when drawing becomes more complicated.
Part of the elimination of flicker is the elimination of the background erase, relying on the fact that the bitmap is a complete replacement of the viewing area, obviating the need for an on screen erasure.
(You erase the bitmap surface instead, as required - and in the PAINT cycle (or other bitmap drawing cycle), not in the background message response).
if I don't handle WM_ERASEBKGND screen is flickering significantly. So how to avoid the future problems ?
# 10 Re: [RESOLVED] Double Buffer (CreateCompatibleDC) black/white screen flashing
if I don't handle WM_ERASEBKGND screen is flickering significantly. So how to avoid the future problems ?
it should not be, can you post all of your code?
# 11 Re: [RESOLVED] Double Buffer (CreateCompatibleDC) black/white screen flashing
You respond to the erase background, with the case like you've done, but you don't actually erase anything.
JVene at 2007-11-9 13:43:11 >

# 12 Re: [RESOLVED] Double Buffer (CreateCompatibleDC) black/white screen flashing
Hm, this implementation brings me a brand new problem which I've never met before.
I have a separate thread using Window for painting graph, it had been flickering until I implemented this above. But now what happened, I put breakpoint inside the code in the thread but when it stops (1 from 3 times, behaves in not deterministic way) entire Windows hangs. System is pretty slow even kill in task manager is not possible, only solution is reboot. I think this might be related to suspend on breakpoint during the copying of the bits.
I tested it on faster (significantly) machine than mine and it didn't appear. But I must note there was Vista and I have XP (VS 2005 + SP1 on both).