现在的位置: 首页 > 自动控制 > 工业·编程 > 正文

利用IPicture接口实现显示BMP/JPG/GIF图像

2013-03-23 22:48 工业·编程 ⁄ 共 3040字 ⁄ 字号 暂无评论

1.问题阐述

在VB 中显示一个图像非常简单,只要将图像控件拖入到面板中,设置相应的属性即可。其实它的显示原理只是调用Windows的Ipicture接口,本节重点介绍了这一接口。

2.实现技巧

如何利用IPicture显示图像呢?首先了解一下这个接口的内容和作用、IPicture接口是一个COM类,操纵着图像对象及其属性。图像对象提供对位图的抽象,而Windows负责BMP、JPG和GIF位图的标准实现。IPictrue接口支持BMP、DIB、EMF、GIF、ICO、JPG、WMF格式图片的显示,但只能保存BMP和ICO格式的图片。下面是IPicture的方法描述
get_Handle 返回图像对象的Windows GDI句柄。
get_Hpal 返回图像对象当前使用的调色板副本。
get_Type返回当前图像对象的图像类型。
get_Width 返回当前图像对象的图像宽度。
get_Height 返回当前图像对象的图像高度。
Render在指定的位置、指定的设备上下文上绘制指定的图像部分。
set_Hpal设置当前图像的调色板。

get_CurDC返回当前选中这个图像的设备上下文。

SelectPicture将一个位图图像选入给定的设备上下文,返回选中图像的设备上下文和图像的GDI句柄。

get_KeepOriginalForma返回图像对象KeepOriginalFormat 属性的当前值。

put_KeepOriginalFormat设置图像对象的KeepOriginalFormat 属性。

PictureChanged通知图像对象它的图像资源改变了。

SaveAsFile将图像数据存储到流中,格式与存成文件格式相同。

get_Attributes返回图像位属性当前的设置。

IPicture接口和其他的接口不同,这个接口的实例不用CoCreateInstance来创建,而是采用一个专门的函数OleLoadPicture创建IPicture接口的实例。OleLoadPicture的声明和参数的含义如下所示:

 

 

STDAPI OleLoadPicture(
IStream * pStream,
LONG lSize,
BOOL fRunmode,
REFIID riid,
VOID ppvObj
);

 

第一个参数pStream指向包含有图像数据的流的指针,第二个参数lSize为从流中读取的字节数,第三个参数fRunmode为图像属性对应的初值,第四个参数riid为涉及到的接口标识描述要返回的接口指针的类型,第五个参数ppvObj为在rrid中用到的接口指针变量的地址。

3.实例代码

本实例使用IPicture接口完成图像JPG和GIF等图像的显示。建立一个基于单文档的工程,工程名为PictureRend。

在PiectureRend.h的函数InitInstance( )中初始化COM库,在程序退出的时候,关闭COM库,加载COM库的代码如下:

BOOL CPictureRendApp::InitInstance()
{
//--------------------------------------------------------------------------
AfxEnableControlContainer();
*****************************
}

 

关闭COM库的代码如下:

 


 

 int CPictureRendApp::ExitInstance() 
{
CoUninitialize();
return CWinApp::ExitInstance();
}

 

在PictureRendView.h中声明:

  

CFile m_File;
IStream* m_pStream ;
IPicture* m_pPicture ;
LONG m_nWidth;
LONG m_nHeight;

 

在打开菜单中,获取打开的图像的路径名,代码如下:

 

void CPictureRendApp::OnFileOpen()
{
CFileDialog dlg(TRUE, NULL, NULL, OFN_HIDEREADONLY
|OFN_OVERWRITEPROMPT,
"文件 (*.jpg)|*.jpg|文件 (*.gif)|*.gif|All Files (*.*)|*.*||", NULL);
if( IDOK != dlg.DoModal())
{
return;
 }
m_strPicPath = dlg.GetPathName();
PostMessage(((CMainFrame*)m_pMainWnd)->GetActiveView()->m_hWnd,
WM_ON_RENDER_PIC,0,0);//一旦打开文件,消息响应
}

 

注意,在响应“打开”消息的时候,要对消息映射的地方加以改变,如下:


 

 ON_COMMAND(ID_FILE_OPEN,OnFileOpen)。

 

在View中添加渲染图像,代码如下:

void CPictureRendView::OnRenderPic()
{
HRESULT hr;
CClientDC dc(this);
m_File.Open( theApp.m_strPicPath, CFile::modeRead | CFile::shareDenyNone );
// 读入文件内容
DWORD dwSize = m_File.GetLength();
HGLOBAL hMem = ::GlobalAlloc( GMEM_MOVEABLE, dwSize );
LPVOID lpBuf = ::GlobalLock( hMem );
m_File.ReadHuge( lpBuf, dwSize );
m_File.Close();
 m_pStream = NULL;
m_pPicture = NULL;
 // 由 HGLOBAL 得到 IStream,参数 TRUE 表示释放 IStream 的同时,释放内存
hr = ::CreateStreamOnHGlobal( hMem, TRUE, &m_pStream );
::GlobalUnlock( hMem );
 ASSERT ( SUCCEEDED(hr) );
hr = ::OleLoadPicture(
m_pStream, dwSize, TRUE, IID_IPicture, ( LPVOID * )&m_pPicture );
ASSERT(hr==S_OK);
long nWidth,nHeight;     // 宽高,MM_HIMETRIC 模式,单位是0.01毫米
m_pPicture->get_Width( &m_nWidth );    // 宽
m_pPicture->get_Height( &m_nHeight );   // 高
////////原大小显示//////
CSize sz( m_nWidth, m_nHeight );
dc.HIMETRICtoDP( &sz );
// 转换 MM_HIMETRIC 模式单位为 MM_TEXT 像素单位
m_pPicture->Render(dc.m_hDC,0,0,sz.cx,sz.cy,
0,m_nHeight,m_nWidth,-m_nHeight,NULL);
}

 

在程序退出时,释放数据流和接口指针:


 

 if ( m_pPicture ) m_pPicture->Release();  // 释放 IPicture 指针
if ( m_pStream ) m_pStream->Release();    // 释放 IStream 指针,同时释放了 hMem

 

运行!

 

 
图12-6  IPicture接口的使用

 

给我留言

留言无头像?