• 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

    界面:

    源码下载

  • 相关阅读:
    2015-03-20——移动端UC浏览器、QQ浏览器自动全屏
    2015-03-18——mongodb的简单配置
    2015-03-12——简析DOM2级样式
    2015-03-12——简析DOM2级事件
    2015-03-11——简析DOM规范
    2015-03-10——简析javascript对象
    分页控件的编写
    Jquery添加掩盖层的插件
    正则表达式/g/i/d
    MVC请求生命周期
  • 原文地址:https://www.cnblogs.com/luo-peng/p/5616990.html
Copyright © 2020-2023  润新知