Thread: Double buffering problem

  1. #1
    george7378
    Guest

    Double buffering problem

    Hi there,

    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:

    Code:
    case WM_PAINT:
    			{
    		    PAINTSTRUCT Ps;
    	        HBRUSH EarthBrush;
    	        HBRUSH SatBrush;
    			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));
    			SelectObject(hdcBuffer, EarthBrush);
    			Ellipse(hdcBuffer, earthxcoord, earthycoord, earthxcoord+(2*6378.14*conversionfactor), earthycoord+(2*6378.14*conversionfactor));
                DeleteObject(EarthBrush);
    			SatBrush = CreateSolidBrush(RGB(0, 250, 0));
                SelectObject(hdcBuffer, SatBrush);
    			Ellipse(hdcBuffer, xcoord, ycoord, xcoord+10, ycoord+10);
    			DeleteObject(SatBrush);
    			BitBlt(hdc, 0, 0, GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN), hdcBuffer, 0, 0, SRCCOPY);
    			SelectObject(hdcBuffer, hbmOldBuffer);
                DeleteObject(hbmBuffer);
                DeleteDC(hdcBuffer);
    	        EndPaint(g_hwndWnd, &Ps);
    	    break;
    			}
    The variables don't make sense to you of course, but can anyone identify why this program still flickers annoyingly?

    Thanks a lot! I will provide more info if necessary.

  2. #2
    - - - - - - - - oogabooga's Avatar
    Join Date
    Jan 2008
    Posts
    2,808
    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.
    The cost of software maintenance increases with the square of the programmer's creativity. - Robert D. Bliss

  3. #3
    Registered /usr
    Join Date
    Aug 2001
    Location
    Newport, South Wales, UK
    Posts
    1,273
    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:-
    Code:
    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);
    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.

  4. #4
    - - - - - - - - oogabooga's Avatar
    Join Date
    Jan 2008
    Posts
    2,808
    To get proper double-buffering you'd have to use DirectX (or OpenGL), which use the buffers on the graphics card.
    The cost of software maintenance increases with the square of the programmer's creativity. - Robert D. Bliss

  5. #5
    train spotter
    Join Date
    Aug 2001
    Location
    near a computer
    Posts
    3,868
    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()
    "Man alone suffers so excruciatingly in the world that he was compelled to invent laughter."
    Friedrich Nietzsche

    "I spent a lot of my money on booze, birds and fast cars......the rest I squandered."
    George Best

    "If you are going through hell....keep going."
    Winston Churchill

  6. #6
    george7378
    Guest
    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

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. How do I do double buffering in console?
    By pliang in forum Game Programming
    Replies: 17
    Last Post: 04-20-2005, 07:19 AM
  2. Double Buffering in mode 12h
    By j0seph in forum C Programming
    Replies: 6
    Last Post: 03-04-2005, 12:09 AM
  3. double buffering for allegro
    By Leeman_s in forum C++ Programming
    Replies: 6
    Last Post: 09-12-2002, 02:45 PM
  4. Text && Double Buffering
    By GaPe in forum C Programming
    Replies: 2
    Last Post: 06-09-2002, 05:46 AM
  5. double buffering in MFC
    By Unregistered in forum Windows Programming
    Replies: 0
    Last Post: 03-07-2002, 12:29 PM