1. 程式人生 > 其它 >MFC中雙快取技術

MFC中雙快取技術

技術標籤:MFC筆記mfc

MFC 在進行繪圖的時候,有些情況可能會發生影象閃爍的現象。這時就需要使用二級快取技術對圖形進行處理。

雙快取技術主要是用於處理以下幾種情況:

1)非客戶區和客戶區不能同步更新畫面造成的閃爍,可以去掉視窗的標題和邊框只在WM_PANINT訊息回撥時繪畫,而在WM_NCPAINT訊息回撥中不繪畫。

2)客戶區內背景和前景不能同步更新畫面,在WM_ERASEBKGND背景更新和WM_PAINT前景更新兩個訊息中,只選擇一種訊息回撥函式。

3)Invalidate強制更新客戶區函式,帶入資源的ID編號載入影象false只更新前景而不更新背景,可以減少客戶區閃爍。或者說帶入false只通過WM_PAINT訊息回撥,而不是通知WM_ERASEBKGND訊息回撥

4)即使只在客戶區中輸出畫面,如果畫面輸出的背景圖和角色圖形太多,還會發生背景圖和交圖發生互相覆蓋而閃爍。解決這個問題的方法就是使用雙緩衝防閃爍技術。

雙快取技術的技術原理:

雙快取技術的原理是將一些需要顯示的圖片先繪製在一個記憶體DC中(裝置上下文中)。繪製將所有要顯示的圖片繪製完成之後,然後直接拷貝至螢幕DC統一將其顯示在視窗中。

相當於一個畫家在作畫的過程不展示給別人,當畫作完成之後在統一拿出來讓別人觀看。

雙快取的使用例子:

此例子是使用MFC中的定時器對圖片進行多次重新整理,顯示多張圖片。分別以使用雙緩衝技術和不使用雙緩衝技術。

  1. 建立需要用到的CBitmap點陣圖物件載入需要顯示的圖片(在.h 檔案中)
CBitmapbitmap;//定義顯示圖片的點陣圖物件
CBitmapmainbitmap;//定義雙緩衝的繪圖點陣圖
CBitmapbit[8];//定義繪圖物件點陣圖陣列,用於載入蝴蝶點陣圖

2.建立在繪圖過程中需要使用的CDC類上下文繪圖裝置(在.h 檔案中)

CDCmainDC;//定義雙緩衝上下文裝置
CDCbackDC;//定義背景圖繪圖裝置
CDCdc[8];//定義蝴蝶突變裝置

3.建立定時器和向點陣圖中載入圖片(在初始化視窗函式中)

bitmap.LoadBitmap(IDB_MAINPICTURE);//載入背景點陣圖

for(inti=0;i<8;i++)//載入蝴蝶點陣圖
{
    bit[i].LoadBitmap(IDB_1+i);
}

SetTimer(1,10,NULL);//設計定時器,沒10ms觸發一次

4.在定時器中顯示需要顯示的圖片

  • 不使用雙緩衝技術程式碼
voidC二級快取Dlg::OnTimer(UINT_PTRnIDEvent)
{
    // TODO: 在此新增訊息處理程式程式碼和/或呼叫預設值
    CClientDCcd(this);//建立客戶區繪圖裝置
    staticinti=0;
    if(i>7)
    {
        i=0;
    }
    //獲取客戶區大小
    CRectrect;
    GetClientRect(rect);//獲取客戶區大小
    //顯示藍色背景
    cd.FillSolidRect(0,0,rect.right,rect.Height(),RGB(0,255,0));//將藍色背景直接繪製在螢幕上
    //建立背景顯示DC,顯示背景圖片
    backDC.CreateCompatibleDC(&cd);//使用零時話圖物件產生與pDC指定裝置相容的裝置上下文記憶體
    backDC.SelectObject(bitmap);//將載入的點陣圖物件物件選入裝置上下文中
    cd.BitBlt(0,0,600,400,&backDC,0,0,SRCCOPY);//將背景圖直接繪製在螢幕上
    //建立蝴蝶顯示DC ,顯示蝴蝶
    dc[i].CreateCompatibleDC(&cd);
    dc[i].SelectObject(bit[i]);
    cd.BitBlt(20,20,300,400,&dc[i],100,20,SRCCOPY);//將蝴蝶直接繪製在螢幕上
    //釋放DC
    dc[i].DeleteDC();//釋放記憶體DC
    backDC.DeleteDC();//釋放記憶體DC
    i++;
    CDialogEx::OnTimer(nIDEvent);
}

展示效果:

  • 使用雙緩衝技術
voidC二級快取Dlg::OnTimer(UINT_PTRnIDEvent)
{
    // TODO: 在此新增訊息處理程式程式碼和/或呼叫預設值
    CClientDCcd(this);
    staticinti=0;
    if(i>7)
    {
        i=0;
    }
    //獲取客戶區大小
    CRectrect;
    GetClientRect(rect);
    CDCmemDC;//用於緩衝作圖記憶體DC
    CBitmapbmp;//記憶體中承載臨時影象的點陣圖mainDC.CreateCompatibleDC(&cd);//依附視窗DC建立相容DC
    mainbitmap.CreateCompatibleBitmap(&cd,rect.Width(),rect.Height());//建立相容點陣圖,cd為最後需要繪製到螢幕上當的繪圖裝置,
    mainDC.SelectObject(&mainbitmap);//將點陣圖選擇進記憶體DC
    //顯示藍色背景
    mainDC.FillSolidRect(0,0,rect.right,rect.Height(),RGB(0,255,0));//在緩衝DC上繪製藍色背景
    建立背景顯示DC,顯示背景圖片
    backDC.CreateCompatibleDC(&mainDC);//使用零時話圖物件產生與pDC指定裝置相容的裝置上下文記憶體
    backDC.SelectObject(bitmap);//將載入的點陣圖物件物件選入裝置上下文中
    mainDC.BitBlt(0,0,600,400,&backDC,0,0,SRCCOPY);//將背景圖片繪製到緩衝DC上
    ///建立蝴蝶顯示DC ,顯示蝴蝶
    dc[i].CreateCompatibleDC(&cd);
    dc[i].SelectObject(bit[i]);
    mainDC.BitBlt(100,100,rect.Width(),rect.Height(),&dc[i],0,0,SRCCOPY);//將蝴蝶圖片繪製到緩衝DC中
    cd.BitBlt(0,0,rect.Width(),rect.Height(),&mainDC,0,0,SRCCOPY);//最後統一將緩衝DC中的內容繪製到螢幕上。
    //釋放DC
    backDC.DeleteDC();//釋放記憶體DC
    mainDC.DeleteDC();//釋放記憶體DC
    dc[i].DeleteDC();//釋放記憶體DC
    mainbitmap.DeleteObject();
    i++;
    CDialogEx::OnTimer(nIDEvent);
}

效果如下: