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

MFC 對話框添加背景圖片完整實現:OnPaint 重繪與 StretchBlt

     編輯:關於C++

實現步驟

1. 資源導入

  • 資源視圖 → 右鍵 Insert → Bitmap
  • 匯入圖片,假設資源 ID 為 `IDB_BITMAP1`

2. OnPaint 重寫

void CMyDialogDlg::OnPaint() {
    if (IsIconic()) {
        // 圖示模式:預設繪製
        CPaintDC dc(this);
        SendMessage(WM_ICONERASEBKGND, reinterpret_cast(dc.GetSafeHdc()), 0);
        
        int cxIcon = GetSystemMetrics(SM_CXICON);
        int cyIcon = GetSystemMetrics(SM_CYICON);
        CRect rect;
        GetClientRect(&rect);
        int x = (rect.Width() - cxIcon + 1) / 2;
        int y = (rect.Height() - cyIcon + 1) / 2;
        dc.DrawIcon(x, y, m_hIcon);
    } else {
        // 正常模式:繪製背景圖片
        CPaintDC dc(this);           // 畫布 DC
        CRect rc;
        GetClientRect(&rc);          // 客戶區矩形
        
        CDC dcMem;                   // 記憶體 DC (雙緩衝)
        dcMem.CreateCompatibleDC(&dc);
        
        CBitmap bmpBackground;
        bmpBackground.LoadBitmap(IDB_BITMAP1);  // 載入資源位圖
        
        BITMAP bitmap;
        bmpBackground.GetBitmap(&bitmap);       // 獲取位圖尺寸
        
        CBitmap* pOldBmp = dcMem.SelectObject(&bmpBackground);  // 選入記憶體 DC
        
        // 關鍵:拉伸繪製填滿客戶區
        dc.StretchBlt(0, 0, rc.Width(), rc.Height(),
                      &dcMem, 0, 0, bitmap.bmWidth, bitmap.bmHeight, SRCCOPY);
        
        dcMem.SelectObject(pOldBmp);  // 恢復原位圖
    }
}

關鍵 API 說明

API用途
`CPaintDC`繪圖設備上下文,自動處理 `BeginPaint`/`EndPaint`
`CDC::CreateCompatibleDC`建立與螢幕相容的記憶體 DC,實現雙緩衝防閃爍
`CBitmap::LoadBitmap`從資源載入位圖
`CBitmap::GetBitmap`獲取位圖寬高資訊 (`BITMAP` 結構)
`CDC::SelectObject`將位圖選入 DC,返回舊位圖指標 (需保存以便恢復)
`CDC::StretchBlt`拉伸位塊傳輸:來源矩形 → 目標矩形自動縮放

進階:背景圖片平鋪而非拉伸

// 替換 StretchBlt 為平鋪迴圈
for (int y = 0; y < rc.Height(); y += bitmap.bmHeight) {
    for (int x = 0; x < rc.Width(); x += bitmap.bmWidth) {
        dc.BitBlt(x, y, bitmap.bmWidth, bitmap.bmHeight, &dcMem, 0, 0, SRCCOPY);
    }
}

常見問題

  • ❌ **圖片不顯示**:資源 ID 拼寫錯誤、未 `LoadBitmap` 成功 (檢查返回值)
  • ❌ **閃爍嚴重**:未使用記憶體 DC 直接在 `dc` 上繪製
  • ❌ **調整大小後殘留**:未處理 `WM_ERASEBKGND` 返回 `TRUE` 防止系統擦除背景

補充:阻止系統擦除背景

BOOL CMyDialogDlg::OnEraseBkgnd(CDC* pDC) {
    return TRUE;  // 由 OnPaint 完全接管背景繪製
}
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved