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

VC++ 使用 IPicture/OleLoadPicture 載入並繪製 JPG 圖片

     編輯:VC 教學

核心思路

利用 OLE 自動化介面 IPicture 搭配 OleLoadPicture,可直接從記憶體串流載入 JPG、BMP、GIF、PNG 等格式,無需第三方庫。適用於 MFC OnDraw 繪製至 CDC。

完整程式碼 (放入 OnDraw)

void CMyView::OnDraw(CDC* pDC)
{
    IPicture *pPic = NULL;
    IStream  *pStm = NULL;
    CFile file;
    CFileStatus fs;
    LONG cb = 0;

    // 1. 開啟檔案並讀入 HGLOBAL
    if (file.Open(_T("test.jpg"), CFile::modeRead) &&
        file.GetStatus(_T("test.jpg"), fs) &&
        (cb = fs.m_size) != -1)
    {
        HGLOBAL hGlobal = GlobalAlloc(GMEM_MOVEABLE, cb);
        if (hGlobal)
        {
            LPVOID pvData = GlobalLock(hGlobal);
            if (pvData)
            {
                file.ReadHuge(pvData, cb);
                GlobalUnlock(hGlobal);

                // 2. 建立串流並載入 IPicture
                if (SUCCEEDED(CreateStreamOnHGlobal(hGlobal, TRUE, &pStm)))
                {
                    if (SUCCEEDED(OleLoadPicture(pStm, fs.m_size, TRUE,
                                                 IID_IPicture, (LPVOID*)&pPic)))
                    {
                        // 3. 取得圖片尺寸 (HIMETRIC 單位: 0.01 mm)
                        OLE_XSIZE_HIMETRIC hmWidth;
                        OLE_YSIZE_HIMETRIC hmHeight;
                        pPic->get_Width(&hmWidth);
                        pPic->get_Height(&hmHeight);

                        // 4. 轉換為裝置像素並繪製
                        CRect rect;
                        GetClientRect(&rect);
                        double drawW = rect.Width();
                        double drawH = rect.Height();

                        // 保持長寬比縮放 (可選)
                        // double ratio = min(drawW/hmWidth, drawH/hmHeight) * ...;

                        HRESULT hr = pPic->Render(pDC->m_hDC,
                                                  0, 0, (long)drawW, (long)drawH,
                                                  0, hmHeight, hmWidth, -hmHeight, NULL);
                        if (FAILED(hr))
                            AfxMessageBox(_T("Render 失敗"));

                        pPic->Release();
                    }
                    else
                        AfxMessageBox(_T("OleLoadPicture 失敗"));
                    pStm->Release();
                }
                else
                    AfxMessageBox(_T("CreateStreamOnHGlobal 失敗"));
            }
            else
                GlobalFree(hGlobal);
        }
    }
    else
        AfxMessageBox(_T("無法開啟圖片檔案"));
}

關鍵 API 說明

API用途
GlobalAlloc/GlobalLock配置可移動全域記憶體,供 CreateStreamOnHGlobal 使用
CreateStreamOnHGlobal將 HGLOBAL 包裝為 IStream (COM 串流介面)
OleLoadPicture從串流載入圖片,回傳 IPicture 介面指標
IPicture::get_Width/Height取得圖片原始尺寸 (HIMETRIC, 0.01mm)
IPicture::Render繪製至 HDC,參數:目標矩形、來源座標 (HIMETRIC)、裁剪矩形

座標轉換提示

// HIMETRIC 轉像素 (對應 pDC 的對應模式)
int PixX = MulDiv(hmWidth,  pDC->GetDeviceCaps(LOGPIXELSX), 2540);
int PixY = MulDiv(hmHeight, pDC->GetDeviceCaps(LOGPIXELSY), 2540);

常見問題

  • Render 失敗 (E_FAIL):檢查 pDC->m_hDC 有效、圖片格式支援、記憶體充足。
  • 大圖載入緩慢:OleLoadPicture 會完整解碼,大量圖片建議使用 GDI+ / WIC / libjpeg 非同步載入。
  • 透明度/Alpha:IPicture 不支援 Alpha 通道渲染,需改用 Gdiplus::Image。
  • 64 位元專案:介面指標相容,但 HGLOBAL 大小限制 2GB,超大檔案需分段串流。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved