Link to home
Start Free TrialLog in
Avatar of saloknairb
saloknairb

asked on

c++ windows double buffering

I have a project....  It does lots of drawing with GDI functions, and sometimes looks kinda of flickery...

So I am hoping for a way to add double buffering to my program with a very small amount of code.  Ya know.. to get rid of the evil flickers..  An example would be great.
Avatar of AlexFM
AlexFM

Conversion of drawing code in MFC SDI project.

Step 1. Drawing without double buffering.

void CSampleView::OnDraw(CDC* pDC)
{
    CSampleDoc* pDoc = GetDocument();
    ASSERT_VALID(pDoc);

    pDC->Rectangle(10, 10, 200, 200);   // any drawing code
}

2. Step 2. Create Draw finction which draws to device context.

void CSampleView::OnDraw(CDC* pDC)
{
    CSampleDoc* pDoc = GetDocument();
    ASSERT_VALID(pDoc);

    Draw(pDC);
}

void CSampleView::Draw(CDC *pDC)
{
    pDC->Rectangle(10, 10, 200, 200);
}

Step 3. Overwrite OnEraseBkgnd anc convert OnDraw by the following way:

void CSampleView::OnDraw(CDC* pDC)
{
    CSampleDoc* pDoc = GetDocument();
    ASSERT_VALID(pDoc);

    CDC memDC;
    CBitmap bmp;
    CRect rect;

    GetClientRect(&rect);
    memDC.CreateCompatibleDC(pDC);
    bmp.CreateCompatibleBitmap(pDC, rect.Width(), rect.Height());
    memDC.SelectObject(&bmp);

    memDC.FillSolidRect(&rect, RGB(255, 255, 255));  // background

    // draw to memory DC
    Draw(&memDC);

    // draw from memory DC to the screen
    pDC->BitBlt(0, 0, rect.Width(), rect.Height(), &memDC, 0, 0, SRCCOPY);
}

void CSampleView::Draw(CDC *pDC)
{
    pDC->Rectangle(10, 10, 200, 200);   // any drawing code
}

BOOL CSampleView::OnEraseBkgnd(CDC* pDC)
{
    return TRUE;      
}

Now you have flicker-free drawing code. If you don't use MFC, you can do the same using API.
Avatar of saloknairb

ASKER

Yeah, I dont use MFC...   So, could you tell me how exactly I can do this using API?  I understand what the code is doing.  Just dont know where to implement it.    
This is code fragment from Windows Hello World application generated by Application Wizard:

case WM_PAINT:
    hdc = BeginPaint(hWnd, &ps);
// TODO: Add any drawing code here...

DrawText(hdc, szHello, strlen(szHello), &rt, DT_CENTER);

EndPaint(hWnd, &ps);
break;

Let's convert it to using memory DC:
I have drawing code all over the place in my application.  Is that a bad thing?
ASKER CERTIFIED SOLUTION
Avatar of AlexFM
AlexFM

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
>> I have drawing code all over the place in my application.  Is that a bad thing?

All drawing code should be placed in WM_PAINT message handler or called from it.
why is it necessary for it to be placed in the message handler?  
When window is shown, restored, or user moves another window above this window, it should be redrawn. In this case Windows sends WM_PAINT message to the window asking it to redraw itself. This ia a reason all drawing code should be placed to WM_PAINT message handler.
The only exception is application which shows animation or movie updating the screen with high frequency.
Thank you so much!!  See....  I never knew that.  I had drawing code all over the damn place.     No wonder I was having trouble with windows clipping against mine and stuff.