图片文件的存在形式并不总是文件形式,有时可能是内存块、也有可能是字节流,比如保存于数据库中的某一图片,用GetChunk方法读取出来后一般保存在一个预先分配的内存块中,我们知道内存块的首地址,内存块的大小,要把这样的图片显示出来,可以自己编写函数按文件结构解析数据,但未免太麻烦,也是没有意义的“制造轮子”的重复工作,不如用windows系统自带的Ipicture的COM组件显示图片来得更简便些。下面是核心代码。技巧是把数据内存块转换成一个内存文件CMemFile,不必把图片文件存储成一个临时文件再读取。
#include <atlbase.h> #include <afxpriv2.h> void CIpicDlg::ShowPic() { CComQIPtr<IPicture>spIPicture; HRESULT m_hr; //unsigned char* pPictureData; //UINT nPictureSize; CRect rc; m_wndPic1.GetClientRect(&rc); CDC* pDC = m_wndPic1.GetDC(); if(m_pPictureData) { CMemFile memfile; memfile.Attach(m_pPictureData,m_nPictureSize); CArchive ar(&memfile, CArchive::load | CArchive::bNoFlushOnDelete); CArchiveStream arcstream(&ar); HRESULT hr = OleLoadPicture((IStream*)&arcstream, 0, FALSE, IID_IPicture, (void**)&spIPicture); ASSERT(SUCCEEDED(hr) && spIPicture); OLE_XSIZE_HIMETRIC hmWidth = 0; OLE_YSIZE_HIMETRIC hmHeight = 0; m_hr = spIPicture->get_Width(&hmWidth); ASSERT(SUCCEEDED(m_hr)); m_hr = spIPicture->get_Height(&hmHeight); ASSERT(SUCCEEDED(m_hr)); spIPicture->Render(pDC->m_hDC, rc.left, rc.top, rc.Width(), rc.Height(), 0, hmHeight, hmWidth, -hmHeight, NULL); CSize sz(hmWidth,hmHeight); pDC->HIMETRICtoDP(&sz); } if (spIPicture) { spIPicture.Release(); } }
其中m_pPictureData为图片数据块首地址,m_nPictureSize为内存块大小。
测试的VS2005的源代码可以在此下载【】。