電影每秒播放 24 幀利用視覺暫留形成連貫畫面。同理,我們在記憶體建立與視窗客戶區等大的位圖,先在記憶體 DC 上繪製完整幀,再一次性 BitBlt 到螢幕,即可消除閃爍、大幅提速。
新增類別 CMemBitmap,作為「電影中的單幀畫布」。所有繪圖操作均針對此位圖進行,再統一顯示。
void CMemBitmap::Init(CWnd* pWnd) {
m_pWnd = pWnd;
CRect rect; pWnd->GetClientRect(&rect);
CreateCompatibleBitmap(pWnd->GetDC(), rect.Width(), rect.Height());
}
void CMemBitmap::TextOut(int x, int y, int iSize, LPCTSTR str, COLORREF color) {
CDC dcMem; dcMem.CreateCompatibleDC(m_pWnd->GetDC());
dcMem.SelectObject(this);
CFont font; font.CreatePointFont(iSize, _T("新細明體"));
CFont* pOld = dcMem.SelectObject(&font);
dcMem.SetTextColor(color);
dcMem.TextOut(x, y, str);
dcMem.SelectObject(pOld);
font.DeleteObject(); dcMem.DeleteDC();
}
void CMemBitmap::Clear(int x1, int y1, int x2, int y2, COLORREF color) {
CDC dcMem; dcMem.CreateCompatibleDC(m_pWnd->GetDC());
dcMem.SelectObject(this);
CBrush brush(color), *pOld = dcMem.SelectObject(&brush);
dcMem.Rectangle(x1, y1, x2, y2);
dcMem.SelectObject(pOld); dcMem.DeleteDC();
}
在視圖類 OnInitialUpdate 初始化位圖並啟動定時器(如 100ms),在 OnTimer 中:
Clear 清畫布BitBlt 到螢幕 DCvoid CTestView::OnTimer(UINT nIDEvent) {
CRect rect; GetClientRect(&rect);
CDC* pDC = GetDC(); CDC dcComp;
dcComp.CreateCompatibleDC(pDC);
dcComp.SelectObject(&m_MemBitmap);
m_MemBitmap.Clear(0,0,rect.Width(),rect.Height(), RGB(0,0,0));
m_MemBitmap.TextOut(10,10,500,_T("固定文字"), RGB(255,255,255));
m_MemBitmap.TextOut(randX, randY, 400, _T("移動文字"), RGB(255,255,0));
pDC->BitBlt(0,0,rect.Width(),rect.Height(), &dcComp, 0,0, SRCCOPY);
dcComp.DeleteDC(); ReleaseDC(pDC);
}
BitBlt 部分矩形)GDI 雙緩衝技術簡單高效,筆者開發的「撲克麻將」即採此法實現流暢發牌、出牌動畫。完整範例可至 CSDN 下載(代碼 9175)。歡迎切磋:Highersoft@yeah.Net