• C++零食:WTL中使用双缓冲避免闪烁


    双缓冲的原理可以这样形象的理解:把电脑屏幕看作一块黑板。首先我们在内存环境中建立一个“虚拟“的黑板,然后在这块黑板上绘制复杂的图形,等图形全部绘制完毕的时候,再一次性的把内存中绘制好的图形“拷贝”到另一块黑板(屏幕)上。采取这种方法可以提高绘图速度,极大的改善绘图效果。

    例如在OnDraw()函数中可以如下所述实现双缓冲,其主要步骤分为四步:

     CPen Pen;
     Pen.CreatePen(PS_INSIDEFRAME,1,RGB(225,225,0));
     CBrush Brush;
     Brush.CreateSolidBrush(RGB(225,225,0));
     CDC dcMem;
     CBitmap bm;
     CRect rc;
     GetClientRect(&rc);
     // Step 1:为屏幕DC创建兼容的内存DC :CreateCompatibleDC()
     dcMem.CreateCompatibleDC(pDC);
     // Step 2:创建位图:CreateCompatibleBitmap()
     bm.CreateCompatibleBitmap(pDC,rc.Width(),rc.Height());
     // Step 3:把位图选入设备环境:SelectObject(),可以理解为选择画布
     dcMem.SelectObject(&bm); 
     dcMem.SelectObject(Pen);
     dcMem.SelectObject(Brush);
     dcMem.Ellipse(0,0,50,50);//画椭圆
     // Step 4:把绘制好的图形“拷贝“到屏幕上:BitBlt()
     pDC->BitBlt(0,0,rc.Width(),rc.Height(),&dcMem,0,0,SRCCOPY);
     dcMem.DeleteDC();
     bm.DeleteObject();
    这样便实现了双缓冲,通过这个方法可以防止在VC中画图时出现屏幕闪烁的情况。

    在自己画的窗口中,有时候会有闪烁现象。为什么会有闪烁现象呢?其实是因为程序在画窗口时需要用背景色清空显示区域,然后再画。由于这两者的反差比较大,就会被人眼睛捕捉到,感觉闪烁。

    双缓冲就是先在内存中把图画好,然后直接复制到屏幕上去,这样的反差就比较小,也就不觉得闪烁了。

     

    绘图1

     

     

    WTL中的CDoubleBufferImpl

    WTL中有现成的双缓冲类实现,可以很方便的使用就达到效果。

    CDoubleBufferImpl 在AtlFrame.h中。

    1.首先继承自CDoubleBufferImpl

    class TCtrl: 
            public CWindowImpl< TCtrl>,  
            public WTL::CDoubleBufferImpl<TCtrl>  // 继承双缓冲类

    2.由于双缓冲类中已经处理了WM_ERASEBKGND 和WM_PAINT消息,所以需要从你的代码中删除对这些消息的处理。然后加上双缓冲的消息处理即可。

        BEGIN_MSG_MAP(TCtrl)
    //        MESSAGE_HANDLER(WM_PAINT,        OnPaint)
            CHAIN_MSG_MAP( WTL::CDoubleBufferImpl<TCtrl>)
        END_MSG_MAP()

    3.增加一个DoPaint函数,函数声明如下:

    void DoPaint(CDCHandle dc);

    4.将原来OnPaint函数中的代码移到DoPaint中,注意原来的CPaintDC需要改用参数中的CDCHandler

    void TCtrl::DoPaint( CDCHandle dc )
    {
        //CPaintDC dc(m_hWnd);

    dc.MoveTo( xx… )
    }

    OK,编译吧。

     

    参考资料

    VC画图不闪烁的方法(双缓冲技术)

    http://hi.baidu.com/lovefqing/blog/item/3f86cdb6cc5c75f830add174.html

    走近WTL--GDI篇

    http://blog.iceyer.net/walk_up_to_wtl_gdi_part

    Visual C++中实现双缓冲的基本原理

    http://www.builder.com.cn/2007/1016/558583.shtml

    Keep it simple!
    作者:N3verL4nd
    知识共享,欢迎转载。
  • 相关阅读:
    url中特殊字符被转义成编码后如何处理
    解决:扰人的报错 Input length must be multiple of 8 when decrypting with padded cipher
    使用fastjson 进行jsonObject转实体类对象
    Mybatis之foreach遍历Map
    Map对象中的keyset()、entryset()和Map.Entry
    jdk的keytool生成jks和获取jks的信息,公匙
    postgres如何不插入重复的值
    docker查看日志记录
    Git Bash输错账号密码如何重新输入
    IntellIJ IDEA 配置 Maven 以及 修改 默认 Repository
  • 原文地址:https://www.cnblogs.com/lgh1992314/p/6616345.html
Copyright © 2020-2023  润新知