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

MFC OnDraw 中載入位圖導致 Assert 失敗的根因與修正

     編輯:程式設計綜合問答

在 MFC OnDraw() 中動態載入位圖並繪製,若寫法不當會觸發 ASSERT 失敗(通常在視窗最大化/最小化重繪時發生)。典型錯誤代碼:

void CMyView::OnDraw(CDC* pDC) {
    static int i = 0;
    m_chessboard.LoadBitmap(IDB_BITMAP1); // ❌ 錯誤位置
    if (i == 0) {
        Chessboard.CreateCompatibleDC(pDC);
        Chessboard.SelectObject(m_chessboard);
        pDC->BitBlt(0, 0, 800, 600, &Chessboard, 0, 0, SRCCOPY);
        i = 1;
    }
}

根因分析

  • OnDraw() 會被頻繁呼叫(重繪、縮放、遮蔽恢復)。
  • CBitmap::LoadBitmap() 若重複呼叫且未先 DeleteObject(),會導致 GDI 物件洩漏或狀態衝突,觸發 MFC 偵測機制的 ASSERT。
  • 靜態變數 i 只讓繪製邏輯執行一次,但 LoadBitmap() 每次都會執行。

正確修法

void CMyView::OnDraw(CDC* pDC) {
    static bool initialized = false;
    if (!initialized) {
        m_chessboard.LoadBitmap(IDB_BITMAP1); // ✅ 移入初始化區塊
        initialized = true;
    }
    if (m_chessboard.m_hObject) { // 確保載入成功
        CDC memDC;
        memDC.CreateCompatibleDC(pDC);
        CBitmap* pOld = memDC.SelectObject(&m_chessboard);
        pDC->BitBlt(0, 0, 800, 600, &memDC, 0, 0, SRCCOPY);
        memDC.SelectObject(pOld);
    }
}

最佳實踐補充

  • 資源載入放在 OnInitialUpdate() 或建構子,而非繪製迴路。
  • 使用 CBitmap 成員變數自動管理生命週期(析構釋放)。
  • 繪圖前檢查 m_hObject != NULL 防禦性編程。
  • 考慮雙緩衝 (CMemDC) 減少閃爍。

核心原則:OnDraw 只負責畫,不負責載入資源。

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