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

MFC 實現 BMP 圖片顯示與背景繪製:從文件加載到雙緩衝渲染全流程

     編輯:關於C語言

整體流程

  1. 文件對話框選擇 BMP → 獲取路徑
  2. 讀取文件到內存緩衝區
  3. 解析 BMP 文件頭/信息頭 → 創建 HBITMAP
  4. OnPaint 中雙緩衝繪製(避免閃爍)

步驟 1:文件選擇對話框

void CShowBMPDlg::OnButtonSelectImage() {
    char szFilter[] = "BMP Files (*.bmp)|*.bmp|All Files (*.*)|*.*||";
    CFileDialog dlg(TRUE, "BMP", NULL, OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT, szFilter);
    if (dlg.DoModal() == IDOK) {
        strPathName = dlg.GetPathName();
        LoadShowBMPFile(strPathName);
        m_hBitmap = BufferToHBITMAP();
        Invalidate(); // 觸發 WM_PAINT
    }
}

步驟 2:加載文件到內存

BOOL CShowBMPDlg::LoadShowBMPFile(const char* pPathname) {
    CFile file;
    if (!file.Open(pPathname, CFile::modeRead)) return FALSE;
    DWORD len = file.GetLength();
    m_pBMPBuffer = new char[len + 1];
    if (!m_pBMPBuffer) return FALSE;
    if (file.Read(m_pBMPBuffer, len) != len) return FALSE;
    return TRUE;
}

步驟 3:內存緩衝區 → HBITMAP(核心解析)

HBITMAP CShowBMPDlg::BufferToHBITMAP() {
    HBITMAP hShowBMP = NULL;
    LPSTR lpBuffer = m_pBMPBuffer;
    BITMAPFILEHEADER bmfHeader;
    DWORD bmfHeaderLen = sizeof(bmfHeader);
    strncpy((LPSTR)&bmfHeader, lpBuffer, bmfHeaderLen);

    if (bmfHeader.bfType != 0x4D42) return NULL; // 'BM'
    LPSTR hDIB = lpBuffer + bmfHeaderLen;
    BITMAPINFOHEADER& bmiHeader = *(LPBITMAPINFOHEADER)hDIB;
    BITMAPINFO& bmInfo = *(LPBITMAPINFO)hDIB;
    m_bmW = bmiHeader.biWidth;
    m_bmH = bmiHeader.biHeight;
    LPVOID lpDIBBits = lpBuffer + bmfHeader.bfOffBits;

    CClientDC dc(this);
    hShowBMP = CreateDIBitmap(dc.m_hDC, &bmiHeader, CBM_INIT, lpDIBBits, &bmInfo, DIB_RGB_COLORS);
    return hShowBMP;
}

關鍵點:

  • 校驗 bfType == 'BM'
  • 直接指釖轉換讀取 BITMAPINFOHEADER、BITMAPINFO
  • bfOffBits 定位像素數據
  • CreateDIBitmap 從設備相關格式創建位圖

步驟 4:雙緩衝繪製(OnPaint)

void CShowBMPDlg::DrawImage(int x, int y, CDC* pDC) {
    CDC MemDC;
    MemDC.CreateCompatibleDC(pDC);
    HBITMAP OldBitmap = (HBITMAP)MemDC.SelectObject(m_hBitmap);
    CBitmap* pBitmap = CBitmap::FromHandle(m_hBitmap);
    if (m_bmW == 0 || m_bmH == 0) return;

    CRect rect;
    GetClientRect(&rect);
    pDC->BitBlt(x, y, rect.Width(), rect.Height(), &MemDC, 0, 0, SRCCOPY);
    MemDC.SelectObject(OldBitmap);
}

雙緩衝優勢:先在內存 DC 繪製,再一次性 BitBlt 到屏幕 DC,消除閃爍。

進階優化建議

  • 縮放/拉伸:用 StretchBlt 或 SetStretchBltMode(HALFTONE) 高質量縮放。
  • 透明色/Alpha:BMP 不支持 Alpha,需手動處理或改用 PNG + GDI+/WIC。
  • 資源管理:m_hBitmap 在 OnDestroy 中 DeleteObject;緩衝區 delete[] m_pBMPBuffer。
  • 大圖優化:分塊加載、異步解碼、僅繪製可見區域。

常見問題排查

現象原因對策
圖片不顯示/全黑CreateDIBitmap 失敗檢查 biBitCount、bfOffBits、DC 是否有效
顏色錯亂調色板未處理 / DIB_RGB_COLORS 錯誤256 色模式需 RealizePalette;真彩色用 DIB_RGB_COLORS
閃爍嚴重無雙緩衝 / OnEraseBkgnd 返回 TRUE雙緩衝 + OnEraseBkgnd 返回 FALSE

總結

MFC 顯示 BMP 核心在於:文件解析 → DIB 創建 → 雙緩衝渲染。掌握 BITMAPFILEHEADER/BITMAPINFOHEADER 結構、CreateDIBitmap/BitBlt API、雙緩衝模式,即可實現高性能圖片顯示。現代項目建議改用 GDI+/WIC/ICO 支持更多格式與 Alpha 通道。

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