MFC製作雙緩衝無閃爍的字幕滾動條

最近一段時間由於項目需要,需要一個字幕滾動條,所以瞭解了一下雙緩衝的繪圖方法。

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.left,rect.top,rect.right,rect.bottom,&memDC,0,0,SRCCOPY);

             

       //清理釋放

       this->ReleaseDC(pDc);

       memDC.DeleteDC();

       memBitmap.DeleteObject();

             

}

5. 總結

採用雙緩衝的方法,可以極大的減少閃爍的現象,提高顯示質量。關於JavaGDI+的雙緩衝的方法,可以參考[url]http://zjyzjy.blog.51cto.com/329429/67374[/url] (Java) [url]http://zjyzjy.blog.51cto.com/329429/67370[/url] (GDI+)

關於具體的實現,可以參考本文的附件,同樣推薦國外的牛人的多線程的實現方法。

 
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章