首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> VC >> VC 教學

MFC 繪圖系列:使用 LoadImage 與 Memory DC 顯示位圖完整實作

     編輯:VC 教學

核心流程

  1. 建立螢幕 DC (CClientDC)
  2. 建立相容記憶體 DC (CDC::CreateCompatibleDC)
  3. 用 Windows API LoadImage 載入位圖取得 HBITMAP
  4. 將位圖選入記憶體 DC (SelectObject)
  5. 取得客戶區矩形,呼叫 BitBlt 繪製到螢幕 DC
  6. 釋放記憶體 DC

關鍵 API:LoadImage 參數詳解

HANDLE LoadImage(
    HINSTANCE hinst,      // 模組實例句柄,檔案載入時傳 NULL
    LPCTSTR lpszName,     // 檔案完整路徑或資源名稱
    UINT uType,           // IMAGE_BITMAP / IMAGE_CURSOR / IMAGE_ICON
    int cxDesired,        // 期望寬度 (像素),0 表示原始大小
    int cyDesired,        // 期望高度
    UINT fuLoad           // LR_LOADFROMFILE (從檔案) | LR_CREATEDIBSECTION 等
);

完整範例程式碼 (OnPaint 中繪製)

void CMyView::OnPaint()
{
    CPaintDC dc(this); // 繪圖 DC,自動 BeginPaint/EndPaint

    // 1. 建立記憶體 DC
    CDC memDC;
    memDC.CreateCompatibleDC(&dc);

    // 2. 載入位圖 (從檔案)
    CBitmap bmp;
    bmp.m_hObject = (HBITMAP)::LoadImage(
        NULL, 
        _T("b1.bmp"), 
        IMAGE_BITMAP, 
        500, 400,           // 強制縮放至 500x400,若要原圖改為 0,0
        LR_LOADFROMFILE | LR_CREATEDIBSECTION
    );

    if (bmp.m_hObject == NULL) {
        AfxMessageBox(_T("載入圖片失敗!"));
        return;
    }

    // 3. 選入記憶體 DC (儲存舊物件)
    CBitmap* pOldBmp = memDC.SelectObject(&bmp);

    // 4. 取得客戶區大小並繪製
    CRect rect;
    GetClientRect(&rect);
    dc.BitBlt(0, 0, rect.Width(), rect.Height(), &memDC, 0, 0, SRCCOPY);

    // 5. 還原並清理 (析構時自動釋放,但手動還原是好習慣)
    memDC.SelectObject(pOldBmp);
    // bmp、memDC 離開作用域自動 DeleteObject/DeleteDC
}

常見錯誤與避坑指南

錯誤現象原因修正
圖片不顯示/全黑LoadImage 路徑錯誤、檔案不存在、或未用 LR_LOADFROMFILE用絕對路徑、檢查檔案存在、加上 LR_CREATEDIBSECTION 確保 DIB 格式
記憶體 DC 內容為空SelectObject 失敗、或位圖格式不支援檢查 bmp.m_hObject != NULL,改用 CImage 或 GDI+ 載入更穩健
閃爍嚴重OnEraseBkgnd 回傳 TRUE 導致背景重繪覆寫 OnEraseBkgnd 回傳 FALSE,或使用雙緩衝 (CMemDC)
縮放比例失真BitBlt 不支援縮放改用 StretchBlt 或 SetStretchBltMode(HALFTONE)

進階:使用 CImage 簡化載入 (MFC 7.0+ / ATL)

CImage img;
img.Load(_T("photo.jpg")); // 支援 JPG/PNG/BMP/GIF/TIFF
// 直接繪製
img.Draw(dc.m_hDC, 0, 0, rect.Width(), rect.Height());

CImage 內部封裝了 GDI+,支援更多格式、自動處理 Alpha 通道,建議新專案優先使用。

資源釋放提醒

  • CBitmap、CDC 為 RAII 類別,離開作用域會自動呼叫 DeleteObject/DeleteDC
  • 若手動 new CDC,**必須在析構函數或適當時機 delete**,否則洩漏 GDI 物件
  • 選入 DC 的舊物件 (pOldBmp) **必須在 DC 銷毀前還原**,否則位圖物件無法刪除
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved