GDI双缓冲绘图

一、简介

在进行复杂图形绘制时,若直接在屏幕DC上进行绘制,则会出现明显的闪烁。闪烁产生的原因是当绘制的图形较为 复杂时,图形绘制过程中就被刷新到屏幕上,导致结果断断续续地显示出来。双缓冲绘图的原理是在另开辟一块内存用于绘制,当所有绘制工作完成后将内存数据一 次性拷贝到屏幕上。

双缓冲绘图步骤:

创建兼容DC(CreateCompatibleDC)

创建兼容位图(CreateCompatibleBitmap)

将兼容位图选入兼容DC(SelectObject)

在兼容DC中进行绘制工作

将兼容DC中的像素拷贝至屏幕DC(BitBlt)

从兼容DC中换出兼容位图(SelectObject)

删除兼容位图(DeleteObject)

删除兼容DC(DeleteObject)

二、实现:

演示程序绘制了从窗口中心发射的300条射线,为了凸显双缓冲的效果,特意在绘制每条线段时添加延时操作(sleep)。可以发现,若直接在屏幕DC上绘制,能够明显感觉到每条线段的绘制过程,而采用双缓冲则无此现象。

直接绘制代码:

void CtestBFDlg::OnBnClickedDirectDraw()
{
    // TODO: 在此添加控件通知处理程序代码
    CPen newPen;
    CPen *pOldPen;
    CBrush newBrush;
    CBrush *pOldBrush;
    CRect zcRect;
    CDC *pDc;
    CPoint cenpoint;
    CPoint point;

    pDc = Picture.GetDC();
    Picture.GetClientRect(&zcRect);
    newPen.CreatePen(PS_SOLID,1,RGB(0,255,0));//画笔
    pOldPen = pDc->SelectObject(&newPen); 
    newBrush.CreateSolidBrush(RGB(255,255,255));//画刷
    pOldBrush=pDc->SelectObject(&newBrush);

    //绘制工作(直接在屏幕DC上作图)
    pDc->FillRect(zcRect,&newBrush);
    float radius=200;
    float degree=0;
    float x,y;
    float cenx,ceny;
    cenx=zcRect.Width()/2.0;
    ceny=zcRect.Height()/2.0;
    cenpoint.x=cenx;
    cenpoint.y=ceny;
    for(int i=0;i<300;i++)
    {
        pDc->MoveTo(cenpoint);
        degree=2*PI/300*i;
        point.x=radius*cos(degree)+cenx;
        point.y=radius*sin(degree)+ceny;
        Sleep(1);        //刻意延时以凸显效果
        pDc->LineTo(point);
    }
    pDc->SelectObject(pOldPen);
    pDc->SelectObject(pOldBrush);
    newBrush.DeleteObject();
    newPen.DeleteObject();
    ReleaseDC(pDc);
}
View Code

双缓冲绘制代码:

void CtestBFDlg::OnBnClickedDFDraw()
{
    // TODO: 在此添加控件通知处理程序代码
    CPen newPen;
    CPen *pOldPen;
    CBrush newBrush;
    CBrush *pOldBrush;
    CRect zcRect;
    CDC *pDc;
    CPoint cenpoint;
    CPoint point;
    pDc = Picture.GetDC();
    Picture.GetClientRect(&zcRect);    
    
    CDC dc;
    dc.CreateCompatibleDC(pDc);//创建兼容DC
    CBitmap memBmp;
    memBmp.CreateCompatibleBitmap(pDc, zcRect.Width(), zcRect.Height());//创建兼容位图
    CBitmap* OldBmp = dc.SelectObject(&memBmp);//将位图选入DC

    newPen.CreatePen(PS_SOLID,1,RGB(255,0,0));
    pOldPen = dc.SelectObject(&newPen); 
    newBrush.CreateSolidBrush(RGB(255,255,255));
    pOldBrush=dc.SelectObject(&newBrush);

    //绘制工作(在兼容DC中作图)
    //****************************************************************
    dc.FillRect(zcRect,&newBrush);    
    float radius=200;
    float degree=0;
    float x,y;
    float cenx,ceny;
    cenx=zcRect.Width()/2.0;
    ceny=zcRect.Height()/2.0;
    cenpoint.x=cenx;
    cenpoint.y=ceny;
    for(int i=0;i<300;i++)
    {
        dc.MoveTo(cenpoint);
        degree=2*PI/300*i;
        point.x=radius*cos(degree)+cenx;
        point.y=radius*sin(degree)+ceny;
        Sleep(1);       //此处刻意延时以凸显效果
        dc.LineTo(point);
    }
    //****************************************************************
    pDc->BitBlt(0,0,zcRect.Width(),zcRect.Height(),&dc,0,0,SRCCOPY);//将兼容DC中位图拷贝至屏幕DC
    dc.SelectObject(pOldPen);
    dc.SelectObject(pOldBrush);
    dc.SelectObject(OldBmp);
    newBrush.DeleteObject();
    newPen.DeleteObject();
    memBmp.DeleteObject();
    dc.DeleteDC();
    ReleaseDC(pDc);
}
View Code

界面:

源码下载

 

转载于:https://www.cnblogs.com/luo-peng/p/5616990.html

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值