CClientDC)CDC::CreateCompatibleDC)LoadImage 載入位圖取得 HBITMAPSelectObject)BitBlt 繪製到螢幕 DCHANDLE 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 等
);
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 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/DeleteDCnew CDC,**必須在析構函數或適當時機 delete**,否則洩漏 GDI 物件pOldBmp) **必須在 DC 銷毀前還原**,否則位圖物件無法刪除