HBITMAPOnPaint 中雙緩衝繪製(避免閃爍)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
}
}
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;
}
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、BITMAPINFObfOffBits 定位像素數據CreateDIBitmap 從設備相關格式創建位圖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) 高質量縮放。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 通道。