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

MFC 顯示 JPG/GIF/BMP 圖片的最佳實踐:IPicture + CPicture 封裝類完整解析

     編輯:關於VC++

問題背景

VB 的 PictureBox 輕鬆顯示 JPG/GIF,MFC 卻無對應控制項。手寫 JPEG 解碼器不現實。Windows 內建 IPicture COM 介面 (OLE 自動化) 已支援 BMP/JPG/GIF/ICO/WMF/EMF 等格式,配合 OleLoadPicture 即可輕鬆載入渲染。

核心原理

  1. 建立 IStream (檔案/資源/記憶體)
  2. OleLoadPicture(pStream, 0, FALSE, IID_IPicture, (void**)&pPicture) 載入圖片
  3. pPicture->Render(hDC, x, y, w, h, 0, hmHeight, hmWidth, -hmHeight, &rect) 繪製 (座標單位為 HIMETRIC)

CPicture 封裝類 (MFC 友善)


class CPicture {
    CComQIPtr m_spIPicture; // 智慧指標管理介面

public:
    // 多重載入來源
    BOOL Load(LPCTSTR pszPathName);           // 檔案
    BOOL Load(CFile* pFile);                  // CFile
    BOOL Load(CArchive& ar);                  // 序列化/資源
    BOOL Load(UINT nResID, LPCTSTR pszType=_T("IMAGE")); // 資源

    // 繪製
    void Render(CDC* pDC, CRect& rcRender, BOOL bStretch=TRUE);
    CSize GetImageSize(); // 回傳 HIMETRIC 或像素尺寸

    // 內部轉換 HIMETRIC ↔ 裝置座標
    static void HMtoDP(CDC* pDC, SIZEL* psizelHM, SIZEL* psizelDP);
    static void DPtoHM(CDC* pDC, SIZEL* psizelDP, SIZEL* psizelHM);
};

Document/View 架構整合


// Document
class CPictureDoc : public CDocument {
    CPicture m_pict;
    virtual void Serialize(CArchive& ar) { if (ar.IsLoading()) m_pict.Load(ar); }
    CPicture* GetPicture() { return &m_pict; }
};

// View
void CPictureView::OnDraw(CDC* pDC) {
    CPictureDoc* pDoc = GetDocument();
    CPicture* pPic = pDoc->GetPicture();
    CRect rc; GetImageRect(rc); // 依縮放比例計算目標矩形
    pPic->Render(pDC, rc);
}

// 背景填充避免閃爍
BOOL CPictureView::OnEraseBkgnd(CDC* pDC) {
    CRect rcClient, rcImage;
    GetClientRect(&rcClient);
    GetImageRect(rcImage);
    pDC->ExcludeClipRect(&rcImage); // 排除圖片區域
    pDC->FillSolidRect(&rcClient, RGB(0,0,0)); // 填充黑色背景
    return TRUE;
}

資源嵌入圖片

.rc 檔加入:


IDR_MYPIC IMAGE MOVEABLE PURE "res\\MyPic.jpg"

程式碼:CPicture pic(IDR_MYPIC); pic.Render(pDC, rc);

CPictureCtrl:對話框直接使用的靜態圖片控制項


class CPictureCtrl : public CStaticLink { // 繼承支援超連結的靜態控制項
    CPicture m_pict;
    CString m_strURL;

    void PreSubclassWindow() {
        CStaticLink::PreSubclassWindow();
        ModifyStyle(0, SS_OWNERDRAW); // 自繪
    }

    void OnPaint() {
        CPaintDC dc(this);
        CRect rc; GetClientRect(&rc);
        m_pict.Render(&dc, rc);
    }

    // 點擊圖片開啟 URL (若有設定)
    void OnLButtonUp(UINT, CPoint) { if (!m_strURL.IsEmpty()) ShellExecute(...); }
};

使用:對話框放 Static 控制項 (ID=IDC_IMG),變數類型 CPictureCtrl,OnInitDialog 中 m_wndImg.SubclassDlgItem(IDC_IMG, this),同 ID 的 IMAGE 資源自動載入。

替代方案:MFC 內建 CPictureHolder

afxctl.h 中的 CPictureHolder 同樣封裝 IPicture,支援 CreateFromFile, CreateFromResource, Render。若不想引入額外類別,可直接使用。

總結

方案優點缺點
CPicture (本文)介面簡潔、支援檔案/資源/序列化/資源、自動座標轉換需複製類別碼
CPictureHolder (MFC)零依賴、內建文件較少、介面略繁瑣
GDI+ Image功能最強 (縮放插值、Alpha、Metafile)需連結 gdiplus.dll、啟動/關閉 GDI+
CImage (ATL/MFC 新版)封裝 GDI+、介面現代VS2008+ 才完整支援

對於 VC6.0 維護專案或需零依賴部署,**CPicture + IPicture 是最佳選擇**。完整原始碼 (含 ImgView 範例) 請參考本文配套下載。

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