首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 程式設計綜合問答

MFC CDC vs CClientDC 區別與釋放規則:GetDC 需 ReleaseDC,CClientDC 析構自動釋放

     編輯:程式設計綜合問答

MFC 繪圖設備上下文 (DC) 兩大常用類:CDC (基類) 和 CClientDC (客戶區 DC),核心區別在於獲取方式與生命周期管理。

類別對比

特性CDC (配合 GetDC/ReleaseDC)CClientDC
獲取方式CDC* pDC = GetDC(); 或 CDC dc; dc.Attach(GetDC());CClientDC dc(this); 構造時自動 GetDC()
釋放責任手動 ReleaseDC(pDC); 或 dc.Detach(); ReleaseDC(hDC);自動 析構函數自動 ReleaseDC()
適用場景長時間持有 DC、跨函數傳遞、非 WM_PAINT 繪圖短時繪圖、函數局部變量、RAII 風格
構造開銷需顯式調用構造即獲取,析構即釋放
繪圖函數所有 GDI 函數所有 GDI 函數 (繼承 CDC)

代碼示例

CDC + 手動管理

void CMyView::OnDraw(CDC* pDC) {
    // 框架傳入的 pDC:由框架管理,不釋放!
    pDC->Rectangle(10, 10, 100, 100);
}

void CMyView::OnLButtonDown(UINT nFlags, CPoint point) {
    CDC* pDC = GetDC(); // 獲取
    if (pDC) {
        pDC->SetPixel(point, RGB(255,0,0));
        ReleaseDC(pDC); // 必須釋放,否則 GDI 泄漏
    }
    
    // 或用栈對象管理
    CClientDC dc(this); // 構造獲取
    dc.SetPixel(point, RGB(0,255,0));
    // 離開作用域自動釋放
}

CClientDC 推薦用法 (RAII)

void DrawSomething(CWnd* pWnd) {
    CClientDC dc(pWnd); // 構造:::GetDC(pWnd->m_hWnd)
    
    CRect rect;
    pWnd->GetClientRect(&rect);
    dc.FillSolidRect(&rect, RGB(240,240,240));
    
    CPen pen(PS_SOLID, 2, RGB(0,0,255));
    CPen* pOldPen = dc.SelectObject(&pen);
    dc.MoveTo(0, 0);
    dc.LineTo(100, 100);
    dc.SelectObject(pOldPen); // 恢復舊筆刷,防止 GDI 物件泄漏
    
    // 函數結束,dc 析構 → ::ReleaseDC(pWnd->m_hWnd, dc.m_hDC)
}

關鍵規則總結

  1. GetDC / BeginPaint → 必須配對 ReleaseDC / EndPaint
  2. CClientDC / CPaintDC / CWindowDC:構造獲取,析構自動釋放,**首選**
  3. CDC::Attach(hDC) 後需 Detach() 再 ReleaseDC(),否則雙重釋放崩潰
  4. SelectObject 選入 GDI 物件 (筆/刷/字體) 必須保存舊物件指針,用完恢復,否則 GDI 物件泄漏
  5. WM_PAINT 內只能用 CPaintDC (BeginPaint/EndPaint),不能用 GetDC

常見錯誤與後果

錯誤代碼後果
CDC* pDC = GetDC(); ... // 忘記 ReleaseDCGDI 句柄泄漏,繪圖失效,系統變慢,最終崩潰
CClientDC dc(this); dc.SelectObject(&pen); // 忘記恢復舊筆筆刷物件泄漏,下次繪圖樣式錯亂
CDC dc; dc.Attach(GetDC()); ... dc.Detach(); // 忘記 ReleaseDC同第一條
CPaintDC dc(this); // 在非 WM_PAINT 用BeginPaint 失敗,繪圖無效

口訣:「CClientDC 靠譜,構造析構全自動;GetDC 要小心,釋放別忘記;SelectObject 存舊指針,用完還原最關鍵。」

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved