在MFC中利用IPicture接口----实现图片显示

来源:互联网 发布:软件游戏开发培训学校 编辑:程序博客网 时间:2024/05/02 22:51

在VC++上显示图片的具体思路是将jpeg、bmp文件加载到堆中,然后在堆中创建一个数据流,接着调用OleLoadPicture函数加载流中的数据到IPicture中,最后调用IPicture接口的Reader方法输出图像信息。

一、 具体操作如下:

1. 创建单文档MFC应用程序,工程名为ShowJPEG.

2. 向视图类中添加成员变量。

IStream* m_pStream;                //定义流对象IPicture* m_pPicture;              //定义接口对象OLE_XSIZE_HIMETRIC m_JPGWidth;     //图像宽度OLE_YSIZE_HIMETRIC m_JPGHeight;    //图像高度HGLOBAL hMem;                      //堆句柄
3. 在视图类的构造函数中从磁盘中加载图像到流中。

CShowJPEGView::CShowJPEGView(){// TODO: add construction code hereCFile file;                                      //定义文件对象file.Open("psb.jpg",CFile::modeReadWrite);       //打开文件DWORD len=file.GetLength();                      //获取文件长度hMem=GlobalAlloc(GMEM_MOVEABLE,len);             //在堆中分配内存LPVOID pData=NULL;                               //定义一个指针对象pData=GlobalLock(hMem);                          //锁定内存区域file.ReadHuge(pData,len);                        //读取图像数据到堆中file.Close();                                    //关闭文件GlobalUnlock(hMem);                              //解除对堆的锁定CreateStreamOnHGlobal(hMem,TRUE,&m_pStream);     //在堆中创建流OleLoadPicture(m_pStream,len,TRUE,IID_IPicture,(LPVOID*)&m_pPicture);   //加载图像m_pPicture->get_Height(&m_JPGHeight);            //获取图像高度m_pPicture->get_Width(&m_JPGWidth);              //获取图像宽度}
4. 在试图类的OnDraw方法中绘制JPEG图像。

void CShowJPEGView::OnDraw(CDC* pDC){CShowJPEGDoc* pDoc = GetDocument();ASSERT_VALID(pDoc);// TODO: add draw code for native data herem_pPicture->Render(pDC->m_hDC,0,0,(int)(m_JPGWidth/26.45),(int)(m_JPGHeight/26.45),0,m_JPGHeight,m_JPGWidth,-m_JPGHeight,NULL);}
5. 运行程序,显示图像。


二、 编写显示图像的函数

在MFC中, 显示位图容易,但是显示JPG等格式却比较麻烦, 在此使用IPicture接口可以很方便的显示bmp,jpg,gif等格式图片 , 但此接口不支持tif  png格式的图片。

void ShowImage(CString str){CclientDC dc(this);IPicture * pImg;IStream  * pStm;CFileStatus fstatus;CFile file;LONG  cb;if (file.Open (str,CFile::modeRead)&&file.GetStatus (str,fstatus)&&((cb=fstatus.m_size )!=-1)){   HGLOBAL  hGlobal=GlobalAlloc(GMEM_MOVEABLE,cb);   LPVOID pvData=NULL;   if(hGlobal!=NULL)   {      if((pvData=GlobalLock(hGlobal))!=NULL)      {         file.ReadHuge (pvData,cb);         GlobalUnlock(hGlobal);         CreateStreamOnHGlobal(hGlobal,TRUE,&pStm);                  if (SUCCEEDED(OleLoadPicture(pStm,fstatus.m_size ,TRUE,IID_IPicture,(LPVOID *)&pPic)))         {            pStm->Release ();            OLE_XSIZE_HIMETRIC hmWidth;            OLE_YSIZE_HIMETRIC hmHeight;                        pImg->get_Width(&hmWidth);            pImg->get_Height (&hmHeight);            CRECT rect;      dc.GetClientRect(&rect);                                   pImg->Render(dc,0,0,rect.Width(),rect.Height(),0,hmHeight,hmWidth,-hmHeight,NULL);            }         else            AfxMessageBox("Error Loading Picture From Stream!");      }   }}else{   AfxMessageBox("can't Open Image File!");}}


三、 使用函数说明

1. COM接口

该接口主要管理图像对象及其属性,图像对象为位图、图标和图元等提供一种与语言无关的抽象。和标准的字体对象一样,系统也提供了对图像对象的标准实现。其主要的接口是IPicture和IPictureDisp,后者是由IDispatch接口派生以便通过自动化对图像的属性进行访问。图像对象也支持外部接口IPropertyNotifySink,以便用户能在图像属性发生改变时作出决定。图像对象也支持IPersistStream接口,所以它能从一个IStream接口的实例对象保存、装载自己,而IStream接口也支持对流对象的数据读写。  

2. OleLoadPicture函数

OleLoadPicture()从包含有图像数据的流中装载图像。该函数简化了基于流的图像对象的创建过程,可以创建一个新的图像对象并且用流中的内容对它进行初始化。其函数原型为:

STDAPI OleLoadPicture( IStream * pStream, //指向包含有图像数据的流的指针
LONG lSize, //从流中读取的字节数
BOOL fRunmode, //图像属性对应的初值
REFIID riid, //涉及到的接口标识,描述要返回的接口指针的类型
VOID ppvObj // 在rrid中用到的接口指针变量的地址) ;

3. Render函数

显示工作主要是由IPicture接口对象的Render函数来完成的,该函数主要用来将图片的指定部分画到指定的设备环境的指定位置。原型如下:

HRESULT Render( HDC hdc, //渲染图像用的设备环境句柄
long x, //在hdc上的水平坐标
long y, //在hdc上的垂直坐标
long cx, //图像宽度
long cy, //图像高度
OLE_XPOS_HIMETRIC xSrc, //在源图像上的水平偏移
OLE_YPOS_HIMETRIC ySrc, //在源图像上的垂直偏移
OLE_XSIZE_HIMETRIC cxSrc,//在源图像上水平拷贝的数量
OLE_YSIZE_HIMETRIC cySrc,//在源图像上垂直拷贝的数量
LPCRECT prcWBounds //指向目标图元设备环境句柄的指针);


参考: http://blog.csdn.net/shuilan0066/article/details/6623122