1. 程式人生 > >MFC雙緩衝繪圖例項

MFC雙緩衝繪圖例項

本人之前一直了解雙緩衝繪圖的基本原理,但是在研究很久之後才大概知道具體的使用過程,本文將詳細介紹本人在實際專案中使用雙緩衝繪圖的案例。

實現功能:主介面顯示某張包含人臉的圖片,通過dlib detector獲取到人臉上的68個關鍵點,繪製在圖片上顯示,然後通過滑鼠拖動圖片上的關鍵點,調整位置,之後儲存。雙緩衝主要能夠解決拖動關鍵點時螢幕閃爍的問題,本文主要側重在雙緩衝的實現,其他功能概不介紹。

具體實現:

1.定義全域性變數:

CDC dc_mem://記憶體繪製dc

CDC *dc://繪圖dc

vector<CPoint> face://儲存人臉中關鍵點的座標

CBitmap bitmap; 
//記憶體繪圖相關變數 CImage image;

2.OnInitDialog()函式中初始化繪圖dc=GetDC();

3.OnEraseBkgnd()函式直接return true;

  新增函式afx_msg BOOL OnEraseBkgnd(CDC* pDC); 

  新增訊息ON_WM_ERASEBKGND();

  這一步很關鍵!!!

4.OnPaint()中呼叫DrawOnBuffer()繪圖

void CEditLmDlg::DrawOnBuffer()
{
    CRgn rgn;
    rgn.CreateRectRgn(0, 0, image_width, image_height);
    dc->SelectClipRgn(&rgn);

    dc_mem.CreateCompatibleDC(dc);
    bitmap.CreateCompatibleBitmap(dc, edit_rect.Width(), edit_rect.Height());
    CBitmap *pOldBit = dc_mem.SelectObject(&bitmap);
    dc_mem.FillSolidRect(edit_rect, dc->GetBkColor());

    dc_mem.SetStretchBltMode(HALFTONE);
    CRect rect(0, 0, image_width, image_height);
    image.Draw(dc_mem.m_hDC, rect);
    
    dc->BitBlt(0, 0, edit_rect.Width(), edit_rect.Height(), &dc_mem, 0, 0,SRCCOPY);
   
    /**將所有的點繪製到dc_mem上*/程式碼略

    dc->SelectClipRgn(NULL);
    dc_mem.DeleteDC();
    bitmap.DeleteObject();
}

函式中CreateRectRgn函式設定裁剪區可以保證重新整理時只重新整理圖片的部分,不重新整理圖片外的其他控制元件,這樣其他控制元件就不會出現閃爍的情況,另外函式結束時要將裁剪區設定為空。

5.至於拖動關鍵點的操作需要呼叫以下三個函式,以及宣告對應的三個訊息即可,在OnLButtonUpOnMouseMove中將變化後的點的座標更新到face中,並呼叫Invalidate()即可。

afx_msg void OnLButtonDown(UINT nFlags, CPoint point);
afx_msg void OnLButtonUp(UINT nFlags, CPoint point);
afx_msg 
void OnMouseMove(UINT nFlags, CPoint point); ON_WM_LBUTTONDOWN() ON_WM_LBUTTONUP() ON_WM_MOUSEMOVE()

 綜上,雙緩衝繪圖的關鍵是怎麼把所有的繪圖操作放到一個繪圖函式中,該過程可能需要很多的全域性變數來儲存繪圖相關資料。