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

MFC 對話框動態載入圖片進階:CBitmap 與 OnPaint 手動繪製實現自適應顯示

     編輯:VC 教學

需求

執行期指定路徑載入 BMP,並自動調整 Picture Control 大小以完整顯示圖片,不變形、不裁切。

完整實作

1. 成員變數


class CDisplayPic : public CDialog
{
    CBitmap m_bmp; // 持有位圖物件
    // ...
};

2. OnInitDialog 載入並調整控件尺寸


BOOL CDisplayPic::OnInitDialog()
{
    CDialog::OnInitDialog();

    if (m_bmp.m_hObject) m_bmp.DeleteObject();

    // LoadImage 取得 HBITMAP (支援檔案路徑)
    HBITMAP hBmp = (HBITMAP)::LoadImage(AfxGetInstanceHandle(),
        _T("c:\\aaa.bmp"), IMAGE_BITMAP, 0, 0,
        LR_CREATEDIBSECTION | LR_LOADFROMFILE);
    if (!hBmp) return FALSE;

    m_bmp.Attach(hBmp);

    // 取得圖片實際寬高
    DIBSECTION ds;
    m_bmp.GetObject(sizeof(ds), &ds);
    int cx = ds.dsBmih.biWidth;
    int cy = ds.dsBmih.biHeight;

    // 調整 Picture Control (IDC_STATIC1) 大小
    CRect rc;
    GetDlgItem(IDC_STATIC1)->GetWindowRect(&rc);
    ScreenToClient(&rc);
    GetDlgItem(IDC_STATIC1)->MoveWindow(rc.left, rc.top, cx, cy, TRUE);

    return TRUE;
}

3. OnPaint 手動繪製至 Picture Control


void CDisplayPic::OnPaint()
{
    // 取得 Picture Control 的 DC
    CPaintDC dc(GetDlgItem(IDC_STATIC1));

    CRect rcClient;
    GetDlgItem(IDC_STATIC1)->GetClientRect(&rcClient);

    // 雙緩衝:記憶體 DC 合成後一次 BitBlt
    CDC memDC;
    memDC.CreateCompatibleDC(&dc);
    CBitmap bmpMem;
    bmpMem.CreateCompatibleBitmap(&dc, rcClient.Width(), rcClient.Height());
    CBitmap* pOldMem = memDC.SelectObject(&bmpMem);

    // 先將對話框背景繪製到記憶體 DC (避免透明背景殘影)
    CWnd::DefWindowProc(WM_PAINT, (WPARAM)memDC.m_hDC, 0);

    // 建立單色遮罩 (可選,用於透明色處理)
    CDC maskDC;
    maskDC.CreateCompatibleDC(&dc);
    CBitmap bmpMask;
    bmpMask.CreateBitmap(rcClient.Width(), rcClient.Height(), 1, 1, NULL);
    CBitmap* pOldMask = maskDC.SelectObject(&bmpMask);
    maskDC.BitBlt(0, 0, rcClient.Width(), rcClient.Height(), &memDC, 0, 0, SRCCOPY);

    // 使用圖片建立紋理筆刷填充
    CBrush brush;
    brush.CreatePatternBrush(&m_bmp);
    dc.FillRect(rcClient, &brush);

    // 合成顯示 (SRCPAINT 實現透明色效果)
    dc.BitBlt(0, 0, rcClient.Width(), rcClient.Height(),
              &memDC, 0, 0, SRCPAINT);

    brush.DeleteObject();
    maskDC.SelectObject(pOldMask);
    memDC.SelectObject(pOldMem);
    // 不呼叫 CDialog::OnPaint(),避免重複繪製
}

關鍵技術點

  • LR_CREATEDIBSECTION:建立 DIB Section 位圖,可直接存取像素位元、支援 GetObject 取得 BITMAPINFOHEADER。
  • CreatePatternBrush:以位圖建立筆刷,FillRect 可自動平鋪填充任意矩形。
  • 雙緩衝 + SRCPAINT:記憶體 DC 合成後一次輸出,SRCPAINT (OR 運算) 可實現簡易透明色效果 (黑色背景變透明)。
  • 控件 DC 繪製:CPaintDC(GetDlgItem(...)) 直接針對 Picture Control 客戶區繪製,不影響對話框其他區域。

支援格式擴充

若需支援 JPEG/PNG/GIF,可改用 IPicture (OLE 圖片物件) 或 GDI+ (Image::FromFile) 載入,再 GetHBITMAP 轉為 HBITMAP 供 CBitmap::Attach 使用。

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