プログラミングメモ →目次

再描画時の画面ちらつき防止(VC++)

Screen Flicker Free Drawing

描画領域が大きい、描画時間がちょっと長い場合は、画面のちらつきが出てしまいます。画面のちらつきを抑えるために、メモリDCを用意して、メモリDC上で描画を行います。メモリDC上の描画が終わったら、BitBlt()関数で、WindowのDCにコピーします。

1.メモリDCを作成します。BOOL CreateCompatibleDC(CDC* pDC)関数で、WindowのDCからメモリDCを作成します。BOOL CreateCompatibleBitmap(CDC* pDC, int nWidth, int nHeight)関数でビットマップを作ります。CBitmap* SelectObject(CBitmap* pBitmap)関数で、ビットマップをメモリDCに設定します。

2.従来の方法と同じように、メモリDC上で描画処理を実装します。

3.メモリDCに描画したイメージを、BOOL BitBlt(int x, int y, int nWidth, int nHeight, CDC* pSrcDC, int xSrc, int ySrc, DWORD dwRop)関数で、WindowのDCにコピーします。

4.例:CViewのOnDraw()で、再描画処理。注意点:OnTimer()関数の中で、Invalidate(BOOL bErase)の引数はFALSEと設定しまいます。DCをコピーする前に、WindowのDCをクリアしないことで、この時点の画面ちらつき発生させないようにします。

void CTestView::DoDrawMem(CDC* pDC)
{
    CRect rc;
    GetClientRect(&rc);
    pDC->FillSolidRect(&rc, (COLORREF)0x00ffffff);
    CBrush brsh(RGB(rand()%256, rand()%256, rand()%256));
    pDC->SelectObject(&brsh);
    pDC->Ellipse(&rc);
}

void CTestView::OnDraw(CDC* pDC)
{
    CDC dcMem;
    CBitmap bmpMem;
    CRect rc;
    GetClientRect(&rc);
    dcMem.CreateCompatibleDC(pDC);
    bmpMem.CreateCompatibleBitmap(pDC, rc.right, rc.bottom);
    CBitmap* pOldBmp = dcMem.SelectObject(&bmpMem);
    DoDrawMem(&dcMem);
    pDC->BitBlt(0, 0, rc.Width(), rc.Height(), &dcMem, 0, 0, SRCCOPY);
}

void CTestView::OnTimer(UINT nIDEvent) 
{
    Invalidate(FALSE);
    CView::OnTimer(nIDEvent);
}