MFC制作双缓冲无闪烁的字幕滚动条

原创作品,允许转载,转载时请务必以超链接形式标明文章  原始出处 、作者信息和本声明。否则将追究法律责任。 http://zjyzjy.blog.51cto.com/329429/67390
最近一段时间由于项目需要,需要一个字幕滚动条,所以了解了一下双缓冲的绘图方法。

1.       闪烁产生原因

首先,介绍一下为什么会产生闪烁。我们在绘图时收到WM_PAINT消息后,系统会调用默认的画刷来填充被Invalidate 的区域,这样由于时间差的原因,会产生闪烁的现象。

2.       双缓冲原理

双缓冲使用内存缓冲区来解决由多重绘制操作造成的闪烁问题。 当启用双缓冲时,所有绘制操作首先呈现到内存缓冲区,而不是屏幕上的绘图图面。所有绘制操作完成后,内存缓冲区直接复制到与其关联的绘图图面。因为在屏幕上只执行一个图形操作,所以消除了由复杂绘制操作造成的图像闪烁。
MFC制作双缓冲无闪烁的字幕滚动条_第1张图片
 

3. 相关的函数介绍

 
1)    为屏幕  DC  创建兼容的内存  DC CreateCompatibleDC()
if(!m_dcMemory.CreateCompatibleDC(NULL)) // CDC m_dcMemory;
{
    ::PostQuitMessage(0);
}
2)    创建位图 CreateCompatibleBitmap()
m_Bmp.CreateCompatibleBitmap(&m_dcMemory, rt.Width(), rt.Height()); // CBitmap m_Bmp;
3)    把位图选入设备环境 SelectObject() 可以理解为选择画布
::SelectObject(m_dcMemory.GetSafeHdc(), m_Bmp);
4)    把绘制好的图形“拷贝“到屏幕上:BitBlt()
pdcView->BitBlt(0, 0, rt.Width(), rt.Height(), &m_dcMemory, 0, 0, SRCCOPY);
详细的函数可以查看MSDN
 

4. 本例中的实现

1)   OnTime的时候调用 DrawHorizontalText 方法
void  CScrollMessageDlg :: OnTimer ( UINT   nIDEvent )
{
// TODO: Add your message handler code here and/or call default
DrawHorizontalText ();
CDialog :: OnTimer ( nIDEvent );
}
2)   双缓冲绘图
void  CScrollMessageDlg :: DrawHorizontalText ()
{
 
        // 若当前要显示的消息为空
        // 清除显示区域
       if (! m_lsShowMessage . size ())
       {
               Invalidate (); // 调用默认画刷 m_Brush 把整个区域涂黑
              return;
       }
 
        // 计算当前滚动文字的文字
       if( m_StringCurrentPos  < - ( m_lsShowMessage [ m_iShowCount ]. GetLength ()* /
               m_logFont . lfWidth  +  m_logFont . lfWidth ))
       {
               m_iShowCount  = (++  m_iShowCount ) %  m_lsShowMessage . size ();
               m_StringCurrentPos  =  m_SystemMetricsCX ;   // 回到起始位置
       }
        // 判断是否暂停,若非,右距离减一
        if(! m_isPause )
               m_StringCurrentPos  =  m_StringCurrentPos  - 1;   // 每步向左移动距离
 
 
        // 双缓冲绘图
        CRect   rect ;
        CDC  * pDc // 屏幕绘图设备
        CDC   memDC // 内存绘图设备
      
        GetClientRect (& rect );     
        pDc  = this-> GetDC (); //  指针
        CBitmap   memBitmap ;
        // 创建内存绘图设备
        memDC . CreateCompatibleDC ( NULL );              
        memBitmap . CreateCompatibleBitmap ( pDc , rect .right, rect . bottom );
        memDC . SelectObject (& memBitmap );
      
        // 自定义绘图函数
      
        memDC . FillSolidRect (0,0, rect . Width (), rect . Height (), RGB (155,0,0));
        memDC . SelectObject (& m_font );
        memDC . SetTextColor ( RGB  (255,180,0));
        memDC . SetBkMode ( TRANSPARENT );
      
        memDC . Rectangle (& rect );
        memDC . FillRect (& rect ,& m_brush );
       memDC . TextOut ( m_StringCurrentPos , m_iYLocation , m_lsShowMessage [ m_iShowCount ]);   
      
      
        // 把内存绘图拷贝到屏幕
        pDc -> BitBlt ( rect .left, rect . top , rect .right, rect . bottom ,& memDC ,0,0, SRCCOPY );
             
        // 清理释放
       this-> ReleaseDC ( pDc );
        memDC . DeleteDC ();
        memBitmap . DeleteObject ();
             
}

5. 总结

采用双缓冲的方法,可以极大的减少闪烁的现象,提高显示质量。关于 Java GDI+ 的双缓冲的方法,可以参考 [url]http://zjyzjy.blog.51cto.com/329429/67374[/url] (Java)[url]http://zjyzjy.blog.51cto.com/329429/67370[/url] (GDI+)
关于具体的实现,可以参考本文的附件,同样推荐国外的牛人的多线程的实现方法。
 

本文出自 “持之以恒,刨根问底” 博客,请务必保留此出处http://zjyzjy.blog.51cto.com/329429/67390

你可能感兴趣的:(MFC制作双缓冲无闪烁的字幕滚动条)