Double buffering problem
I am trying to get my program to double buffer, with no success. Basically, the program calls InvalidateRect whenever a timer (50 milliseconds) ticks, and here is what I have in WM_PAINT:
The variables don't make sense to you of course, but can anyone identify why this program still flickers annoyingly?
HDC hdc = BeginPaint(g_hwndWnd, &Ps);
HDC hdcBuffer = CreateCompatibleDC(hdc);
HBITMAP hbmBuffer = CreateCompatibleBitmap(hdc, GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN));
HBITMAP hbmOldBuffer = (HBITMAP)SelectObject(hdcBuffer, hbmBuffer);
EarthBrush = CreateSolidBrush(RGB(0, 0, 250));
Ellipse(hdcBuffer, earthxcoord, earthycoord, earthxcoord+(2*6378.14*conversionfactor), earthycoord+(2*6378.14*conversionfactor));
SatBrush = CreateSolidBrush(RGB(0, 250, 0));
Ellipse(hdcBuffer, xcoord, ycoord, xcoord+10, ycoord+10);
BitBlt(hdc, 0, 0, GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN), hdcBuffer, 0, 0, SRCCOPY);
Thanks a lot! I will provide more info if necessary.
It doesn't look like this program would be very long. If you posted the whole thing I could try running it.
A couple of points. You could create your brushes in WM_CREATE and destroy them in WM_DESTROY. You could do the same with hdcBuffer and hdmBuffer, and leave hdmBuffer selected into hdcBuffer.
My suggestion would be to make the backbuffer DC (hdcBuffer) a static variable declared at the beginning of the window procedure, created in WM_CREATE and deleted in WM_DESTROY.
Do all your weird Ellipse(...) stuff during the WM_TIMER notification, before InvalidateRect.
Reduce WM_PAINT to a simple BeginPaint, BitBlt, EndPaint using the information provided in PAINTSTRUCT:-
That way, when you drag another window across it doesn't continuously redraw the backbuffer AND blit the whole thing when only a smaller area needs to be updated. ;)
BitBlt(Ps.hdc, Ps.rcPaint.left, Ps.rcPaint.top, Ps.rcPaint.right - Ps.rcPaint.left, Ps.rcPaint.bottom - Ps.rcPaint.top, hdcBuffer, ps.rcPaint.left, ps.rcPaint.top, SRCCOPY);
To get proper double-buffering you'd have to use DirectX (or OpenGL), which use the buffers on the graphics card.
In addition to SMurf;
You are leaking 2 GDI brushes each paint (and possibly more GDI resources), because GDI objects (generally) can not be deleted while selected into a DC.
Catch the default when you select the first brush in, replace the default before you clean up the mem DC, as you are doing with the BITMAP.
Handle WM_ERASEBKGND (just return true to stop the background being redrawn as well each paint)
In WM_PAINT only re-draw the rect in the paintstruct, and only InvalidateRect() the smallest area you can.
Bypass the OS msg queue by using InvalidateRect() followed by UpdateWindow()
Hi, sorry for the delay, but thanks for your help. I have re-jigged it according to your advice, and there is no more flickering. I also thank you for making the general improvements to my code - hopefully I will get better as I learn more GDI. Thanks again :)