双缓冲避免刷新时的闪烁

 

在图形图形处理过程中,双缓冲是一项基本的技术。我们都知道,如果窗体在响应WM_PAINT消息的时候要进行复杂的图形处理,由于窗体在频繁的用背景色来擦除原有图形,引起了很大的视觉反差。从而引起了闪烁。解决这一问题的有效方法就是双缓冲技术。

窗体在刷新时,总要有一个擦除原来图像的过程。虚函数OnEraseBkgnd利用背景色填充窗体绘图区,然后再调用新的绘图代码进行重绘,这样擦除再重绘的过程就引起了视觉上的反差。

既然是因为背景色擦除图像引起的闪烁,那么我们就把背景色删除,但是这样的话再重绘时,原来的图形没有擦除,再添加上新的图形,这样看起来更乱了。所以只是去掉背景色还是不够的。到这里我们想到用位图来直接覆盖视区,在这个位图上绘制图形。把一个位图拷贝到视区中显示,有一个BitBlt函数,因为是整个内存块的复制,所以速度很快。

我们来做一个比较看看。。。。。。。

1,新建一个名为DBB的单文档程序,在视类中添加

CDC m_dcMem;            // 内存DC

    CBitmap m_bmp;          // 内存DC中的位图

    int m_nRadius;          // 位图上要画的圆的半径

    enum STATE_DRAW         // 选择的绘制方式

    {

        STATE_NONE,         // 为选择绘制模式

        STATE_NORMAL,       // 选择了普通的绘制模式

        STATE_DBB           // 选择了双缓冲绘制模式

    };

    STATE_DRAW m_stateDraw;

 

    void OnDrawNormal();

    void OnDrawDbb();

2,我们在创建完程序后,第一个执行的函数OnInitialUpdate()中添加如下代码:

    CRect rc;

    GetClientRect(&rc);

    // 为屏幕DC创建兼容的内存DC

    if (!m_dcMem.CreateCompatibleDC(NULL))

        ::PostQuitMessage(0);

    // 创建兼容位图

    m_bmp.CreateCompatibleBitmap(&m_dcMem, rc.Width(), rc.Height());

    m_dcMem.SelectObject(&m_bmp);

 

    SetTimer(1, 100, 0);

//我们要在OnTimer中重绘圆,使其一直刷新,普通的绘制方式会出现明显的闪烁的现象。

//而双缓冲的闪烁现象很不明显

3,定义上面定义的两个函数

void CDBBView::OnDrawNormal()

{

    CDC *pDC = GetDC();

    CRect rc;

    GetClientRect(&rc);

    // 用白色填充

    pDC->FillSolidRect(&rc, 0x00FFFFFF);

    for (int i = 0; i < rc.Width() - 1; i += 16)

    {

        for (int j = 0; j < rc.Height() - 1; j += 16)

        {

            pDC->Ellipse(i, j, i + m_nRadius, j + m_nRadius);

        }

    }

    ReleaseDC(pDC);

}

 

void CDBBView::OnDrawDbb()

{

    CDC *pDC = GetDC();

    CRect rc;

    GetClientRect(&rc);

    m_dcMem.FillSolidRect(&rc, 0x00FFFFFF);

    // 画圆

    for(int i = 0; i < rc.Width() - 1; i+= 16)

    {

        for(int j = 0; j < rc.Height() - 1; j+= 16)

        {

            m_dcMem.Ellipse(i, j, i + m_nRadius, j + m_nRadius);

        }

    }

   

    // 一次性的将内存设备环境上绘制完毕的图形""到屏幕上

    pDC->BitBlt(0, 0, rc.Width(), rc.Height(), &m_dcMem, 0, 0, SRCCOPY);

    ReleaseDC(pDC);

}

我们添加两个菜单,用来选择是用普通绘制方式还是用双缓冲绘制方式绘图。

IDM_NORMAL          普通绘制

IDM_DBB             双缓冲绘制

在视类中添加消息响应,响应代码如下:

void CDBBView::OnNormal()

{

    // TODO: Add your command handler code here

    m_stateDraw = STATE_NORMAL;

}

 

void CDBBView::OnDbb()

{

    // TODO: Add your command handler code here

    m_stateDraw = STATE_DBB;

}

 

void CDBBView::OnUpdateNormal(CCmdUI* pCmdUI)

{

    // TODO: Add your command update UI handler code here

    pCmdUI->SetCheck(STATE_NORMAL == m_stateDraw);

}

 

void CDBBView::OnUpdateDbb(CCmdUI* pCmdUI)

{

    // TODO: Add your command update UI handler code here

    pCmdUI->SetCheck(STATE_DBB == m_stateDraw);

}

好了,现在添加OnTimer()函数,来处理画圆的动作。具体代码如下:

void CDBBView::OnTimer(UINT nIDEvent)

{

    // TODO: Add your message handler code here and/or call default

    if (STATE_NONE == m_stateDraw)

    {

        CView::OnTimer(nIDEvent);

        return;

    }

    if (m_nRadius < 16)

        ++m_nRadius;

    else

        m_nRadius = 0;

    if (STATE_NORMAL == m_stateDraw)

        OnDrawNormal();

    else if (STATE_DBB == m_stateDraw)

        OnDrawDbb();

   

    CView::OnTimer(nIDEvent);

}

自己试试,在用普通绘制方式时会出现明显的闪烁现象,在使用双缓冲绘制方式时基本上没有闪烁显现。

哎,转帖的别人的贴,写的语句不通,呵呵,凑合着看吧,有想要源码的联系我。。。。。。。。

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值