1.      闪烁产生原因
首先,介绍一下为什么会产生闪烁。我们在绘图时收到WM_PAINT消息后,系统会调用默认的画刷来填充被Invalidate 的区域,这样由于时间差的原因,会产生闪烁的现象。
2.      双缓冲原理
双缓冲使用内存缓冲区来解决由多重绘制操作造成的闪烁问题。当启用双缓冲时,所有绘制操作首先呈现到内存缓冲区,而不是屏幕上的绘图图面。所有绘制操作完成后,内存缓冲区直接复制到与其关联的绘图图面。因为在屏幕上只执行一个图形操作,所以消除了由复杂绘制操作造成的图像闪烁。
 
3. 相关的函数介绍
1)  为屏幕 DC 创建兼容的内存 DCCreateCompatibleDC()
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.p,rect.right,rect.bottom,&memDC,0,0,SRCCOPY);
       
    //清理释放
    this->ReleaseDC(pDc);
    memDC.DeleteDC();
    memBitmap.DeleteObject();
       
}
5. 总结
采用双缓冲的方法,可以极大的减少闪烁的现象,提高显示质量。关于JavaGDI+的双缓冲的方法,可以参考[url]zjyzjy.blog.51cto/329429/67374[/url] (Java) [url]zjyzjy.blog.51cto/329429/67370[/url] (GDI+)

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。