MFC 僅原生支援 BMP。JPG/GIF 壓縮率高、檔案小,適合資源嵌入或外部載入。利用系統內建 OleLoadPicture + IPicture COM 介面可零第三方庫顯示。
// 從 IStream 載入圖片
HRESULT OleLoadPicture(
IStream* pStream, // 包含圖片資料的流
LONG lSize, // 讀取位元組數
BOOL fRunmode, // TRUE=執行模式
REFIID riid, // IID_IPicture
void** ppvObj // 輸出 IPicture**
);
// IPicture::Render 繪製到 DC
HRESULT Render(
HDC hdc, long x, long y, long cx, long cy,
OLE_XPOS_HIMETRIC xSrc, OLE_YPOS_HIMETRIC ySrc,
OLE_XSIZE_HIMETRIC cxSrc, OLE_YSIZE_HIMETRIC cySrc,
const RECT* pRcWBounds); // 目標矩形 (HIMETRIC 單位),NULL 為預設
CFileDialog 篩選 *.jpg;*.gif,取得路徑 m_strPath。CFile file; CFileStatus fs;
if (file.Open(m_strPath, CFile::modeRead) && file.GetStatus(fs) && fs.m_size > 0) {
HGLOBAL hGlobal = GlobalAlloc(GMEM_MOVEABLE, fs.m_size);
LPVOID pData = GlobalLock(hGlobal);
file.ReadHuge(pData, fs.m_size);
GlobalUnlock(hGlobal);
IStream* pStream = NULL;
CreateStreamOnHGlobal(hGlobal, TRUE, &pStream); // TRUE: 釋放時自動 Free hGlobal
}
IPicture* pPic = NULL;
HRESULT hr = OleLoadPicture(pStream, fs.m_size, TRUE, IID_IPicture, (void**)&pPic);
pStream->Release(); // OleLoadPicture 內部 AddRef,這裡 Release 平衡
if (FAILED(hr) || !pPic) { AfxMessageBox(_T("載入失敗")); return; }
long hmW, hmH;
pPic->get_Width(&hmW); pPic->get_Height(&hmH); // 单位: 0.01 mm (HIMETRIC)
int scrW = pDC->GetDeviceCaps(HORZRES); // 螢幕寬像素
int scrH = pDC->GetDeviceCaps(VERTRES);
int scrMMW = pDC->GetDeviceCaps(HORZSIZE); // 螢幕寬毫米
int scrMMH = pDC->GetDeviceCaps(VERTSIZE);
double pixW = (double)scrW * hmW / (scrMMW * 100.0); // HIMETRIC=0.01mm
double pixH = (double)scrH * hmH / (scrMMH * 100.0);
HRESULT hr = pPic->Render(pDC->m_hDC, 0, 0, (long)pixW, (long)pixH,
0, hmH, hmW, -hmH, NULL); // ySrc=hmH, cySrc=-hmH 翻轉 Y 軸 (GDI 原點左上,HIMETRIC 原點左下)
if (FAILED(hr)) AfxMessageBox(_T("繪製失敗"));
pPic->Release();
OleLoadPicture 支援 BMP/JPG/GIF/ICO/WMF/EMF 等系統註冊解碼器格式。ySrc = hmHeight, cySrc = -hmHeight 修正座標系差異。CreateStreamOnHGlobal(..., TRUE) 讓流負責釋放 HGLOBAL;IPicture 需手動 Release。SUCCEEDED/FAILED。| 優點 | 缺點 |
|---|---|
| 零第三方依賴,系統內建 | 需初始化 COM (AfxOleInit 或 CoInitialize) |
| 支援常見壓縮格式 | 大圖載入較慢 (無快取/解碼控制) |
| 程式碼簡潔 | 無法存取像素級資料、無動畫支援 (GIF 僅顯示第一幀) |