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

在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 here
	CFile 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 here
	m_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

你可能感兴趣的:(C/C++学习)