首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 程式設計疑難解答

MFC 圖片顯示不出來:GDI+ 初始化缺失、路徑錯誤、繪製時機錯誤三大核心原因與完整修正代碼

     編輯:程式設計疑難解答

核心原因排查清單

  1. GDI+ 未初始化 / 未關閉 (最常見):MFC 默認不自動初始化 GDI+,必須在 `CWinApp::InitInstance` 中調用 `GdiplusStartup`,`ExitInstance` 中 `GdiplusShutdown`。
  2. 圖片路徑錯誤 / 文件不存在:相對路徑在發布後失效,需用絕對路徑或資源嵌入。
  3. 在錯誤位置繪圖:必須在 `OnPaint` / `OnDraw` 中繪製,並在 `CPaintDC` / `CDC` 繪圖上下文有效時調用 `Graphics::DrawImage`。
  4. Image 對象構造失敗:未檢查 `m_img.GetLastStatus()` 是否為 `Ok`。
  5. 坐標/矩形錯誤:繪製目標矩形超出客戶區或尺寸為 0。

完整修正步驟與代碼

1. 應用程序類初始化 GDI+ (關鍵)

// MyApp.h
class CMyApp : public CWinApp {
public:
    virtual BOOL InitInstance();
    virtual int ExitInstance();
private:
    ULONG_PTR m_gdiplusToken;
};

// MyApp.cpp
#include 
#pragma comment(lib, "gdiplus.lib")

BOOL CMyApp::InitInstance() {
    // 初始化 GDI+
    Gdiplus::GdiplusStartupInput gdiplusStartupInput;
    Gdiplus::GdiplusStartup(&m_gdiplusToken, &gdiplusStartupInput, NULL);
    
    // ... 原有初始化代碼 ...
    return TRUE;
}

int CMyApp::ExitInstance() {
    // 關閉 GDI+
    Gdiplus::GdiplusShutdown(m_gdiplusToken);
    return CWinApp::ExitInstance();
}

2. 視圖/對話框類加載並繪製圖片

// MyView.h
class CMyView : public CView {
    // ...
protected:
    Gdiplus::Image* m_pImage; // 指針,便於錯誤處理
    afx_msg void OnPaint();
    DECLARE_MESSAGE_MAP()
};

// MyView.cpp
void CMyView::OnInitialUpdate() {
    CView::OnInitialUpdate();
    
    // 1. 確定圖片絕對路徑 (示例: 程序目錄下 images 文件夾)
    TCHAR szPath[MAX_PATH];
    GetModuleFileName(NULL, szPath, MAX_PATH);
    PathRemoveFileSpec(szPath);
    PathAppend(szPath, _T("images\\test.png")); // 需 #include  + lib
    
    // 2. 構造 Image 對象 (支持 png/jpg/bmp/gif/tiff)
    m_pImage = new Gdiplus::Image(szPath);
    
    // 3. 關鍵:檢查加載狀態
    if (m_pImage->GetLastStatus() != Gdiplus::Ok) {
        AfxMessageBox(_T("圖片加載失敗: ") + CString(szPath));
        delete m_pImage;
        m_pImage = nullptr;
    }
}

void CMyView::OnPaint() {
    CPaintDC dc(this); // 繪圖設備上下文
    
    if (m_pImage) {
        // 4. 創建 GDI+ Graphics 綁定 HDC
        Gdiplus::Graphics graphics(dc.m_hDC);
        
        // 5. 設置高質量插值模式 (可選)
        graphics.SetInterpolationMode(Gdiplus::InterpolationModeHighQualityBicubic);
        
        // 6. 計算繪製矩形 (居中顯示示例)
        CRect rect;
        GetClientRect(&rect);
        int imgW = m_pImage->GetWidth();
        int imgH = m_pImage->GetHeight();
        int x = (rect.Width() - imgW) / 2;
        int y = (rect.Height() - imgH) / 2;
        Gdiplus::Rect destRect(x, y, imgW, imgH);
        
        // 7. 繪製
        graphics.DrawImage(m_pImage, destRect);
    }
    
    // 不要調用 CView::OnPaint() 進行繪圖文檔視圖架構除外
}

void CMyView::OnDestroy() {
    if (m_pImage) {
        delete m_pImage;
        m_pImage = nullptr;
    }
    CView::OnDestroy();
}

3. 對話框版本 (CDialogEx) 關鍵差異

// 在 OnInitDialog 中加載
BOOL CMyDlg::OnInitDialog() {
    CDialogEx::OnInitDialog();
    // ... 加載 m_pImage 同前 ...
    return TRUE;
}

// 在 OnPaint 中繪製
void CMyDlg::OnPaint() {
    CPaintDC dc(this);
    if (m_pImage) {
        Gdiplus::Graphics g(dc.m_hDC);
        CRect rc;
        GetClientRect(&rc);
        g.DrawImage(m_pImage, 0, 0, rc.Width(), rc.Height()); // 拉伸填充
    }
    // CDialogEx::OnPaint() 會繪製背景/控件,通常最後調用或不調用
    CDialogEx::OnPaint(); 
}

常見錯誤對照表

現象可能原因解決
空白無圖片GDI+ 未啟動App::InitInstance 調用 GdiplusStartup
運行時崩潰m_pImage 為 nullptr 仍調用 DrawImage繪製前判斷 if (m_pImage)
找不到文件相對路徑 "test.png" 發布後失效用 GetModuleFileName 獲取程序目錄拼接絕對路徑
圖片變形/不全目標矩形尺寸錯誤計算 destRect 根據客戶區與圖片原始尺寸
內存泄漏未 delete m_pImage / 未 GdiplusShutdownOnDestroy/ExitInstance 釋放

總結

MFC 顯示圖片三步走:**App 初始化 GDI+ → 視圖/對話框 OnInitialUpdate/OnInitDialog 加載 Image 檢查狀態 → OnPaint 中 Graphics::DrawImage 繪製**。嚴格檢查 `GetLastStatus()`、使用絕對路徑、正確釋放資源,即可穩定顯示 PNG/JPG 等格式圖片。

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