编程词典
明日图书
明日软件
用户注册
用户登录
站内
  当前位置:编程词典服务网 >> 编程词典社区论坛 >> 使用GDI+显示GIF图像
  · 使用GDI+显示GIF图像 

用户:  大麦
发帖:  430 篇
作品:  0 个
回复:  110 篇
技术分:  1160 分
等级:  
注册:  2010-05-11 09:09:40



发表于:2010-07-13 16:45:08
          楼主

使用GDI+显示GIF图像
GIF(Graphics Interchange Format,图形交换格式)文件是由 CompuServe公司开发的图形文件格式,用户在浏览网页时,可以经常看到GIF格式的动画。在设计应用程序时,该如何显示GIF动画呢?
用户可以通过显示JPEG图像的方法显示GIF图像,但是它只能显示一幅静态的图像,如果GIF文件中包含有多帧,不能显示动画效果。下面将介绍如何使用GDI+实现GIF动画的显示。GDI+中提供了一个Image类,使用该类的GetFrameDimensionsCount方法可以获取GIF文件中的帧的维数,通过GetFrameDimensionsList方法获取图像帧的GUID,通过GetFrameCount方法根据GUID获取图像的帧数,通过SelectActiveFrame方法设置图像显示的当前帧,最后使用Graphics类的DrawImage方法显示当前帧的图像就可以了。下面通过一个示例介绍GIF图像的显示。
例如,显示GIF图像
(1)创建一个文档/视图结构的应用程序,工程名称为“ShowGIF”。
(2)引用GID+的头文件、命名空间和库文件。
#include "Gdiplus//Gdiplus.h"    //引用头文件 
using namespace Gdiplus;    //引用命名空间
#pragma comment (lib,"Gdiplus//gdiplus.lib") //引用库文件
(3)向视图类中添加成员变量
GdiplusStartupInput m_Gdiplus;   //定义GDI+初始化变量
ULONG_PTR m_pGdiToken;    //定义GID+标识
Bitmap *m_pBmp;      //定义位图对象,派生于Image类
UINT m_Count;       //记录维数
UINT m_FrameCount;     //帧数
PropertyItem* pItem ;     //定义图像属性
int fcount;        //定义一个临时整型变量
UINT delay;       //第一帧的延时
(4)在视图类的构造函数中初始化GDI+,并读取GIF文件的相关信息。
CShowGIFView::CShowGIFView()
{
 GdiplusStartup(&m_pGdiToken,&m_Gdiplus,NULL);  //初始化GDI+
 m_pBmp = Bitmap::FromFile(L"query.gif");   //加载GIF图像
 m_Count = m_pBmp->GetFrameDimensionsCount(); //获取帧维数
 GUID *pGuids = new GUID[m_Count];    //定义一个GUID数组
 m_pBmp->GetFrameDimensionsList(pGuids,m_Count); //获取图像帧的GUID
 m_FrameCount = m_pBmp->GetFrameCount(pGuids); //获取GIF帧数
 UINT size;         //定义一个整型变量
 m_Count = 0;         //初始化成员变量
 m_pBmp->GetPropertySize(&size,&delay);   //获取属性大小
 PropertyItem *pItem = NULL;      //定义属性指针
 pItem = (PropertyItem*)malloc(size);     //为属性指针分配合适的空间
 m_pBmp->GetAllPropertyItems(size,delay,pItem);  //获取属性信息
 delay = ((long*)pItem->value)[0];     //获取第一帧的延时
free(pItem);         //释放属性对象
 delete [] pGuids;        //释放GUID
 fcount = 0;         //初始化成员变量
}
(5)定义一个内存画布类,防止图像闪烁。
class CMemDC : public CDC        //定义一个CmemDC类
{
private:
 CBitmap* m_bmp;        //定义一个位图对象
 CBitmap* m_oldbmp;       //定义一个位图对象
 CDC*  m_pDC;       //定义一个设备上下文指针
 CRect  m_Rect;       //定义一个区域对象
public:
 CMemDC(CDC* pDC, const CRect& rect) : CDC()  //定义构造函数
 {
  CreateCompatibleDC(pDC);     //创建一个兼容的设备上下文
  m_bmp = new CBitmap;      //为位图对象分配空间
  //创建位图对象
  m_bmp->CreateCompatibleBitmap(pDC, rect.Width(), rect.Height());
  m_oldbmp = SelectObject(m_bmp);    //选中创建的位图
  m_pDC = pDC;        //设置成员变量
  m_Rect = rect;        //设置区域对象
  this->BitBlt(m_Rect.left, m_Rect.top, m_Rect.Width(), m_Rect.Height(),
   pDC, m_Rect.left, m_Rect.top,WHITENESS); //绘制白色背景
 }
 ~CMemDC()          //析构函数
 {
  m_pDC->BitBlt(m_Rect.left, m_Rect.top, m_Rect.Width(), m_Rect.Height(),
    this, m_Rect.left, m_Rect.top,SRCCOPY);//绘制图像
  SelectObject(m_oldbmp);      //选中原来的位图对象
  if (m_bmp != NULL)        //判断位图对象是否为空
   delete m_bmp;       //删除位图对象
  DeleteObject(this);       //释放设备上下文
 }
};
(6)处理视图类的WM_TIMER消息,按照一定的时间间隔绘制不同的图像帧。
void CShowGIFView::OnTimer(UINT nIDEvent)
{
 GUID Guid = FrameDimensionTime;     //定义一个GUID
 CDC* pDC = GetDC();       //获取视图窗口的设备上下文
 //定义一个内存画布
 CMemDC dc(pDC,CRect(0,0,m_pBmp->GetWidth(),m_pBmp->GetHeight()));
 Graphics gh(dc.m_hDC);        //定义一个图像对象
 //向设备上下文中绘制图像
 gh.DrawImage(m_pBmp,0,0,m_pBmp->GetWidth(),m_pBmp->GetHeight());
 m_pBmp->SelectActiveFrame(&Guid,fcount++);  //设置下一帧
 if(fcount == m_FrameCount)       //判断当前帧是否为尾帧
    fcount = 0;          //将当前帧设置为第一帧
 CView::OnTimer(nIDEvent);
}
 注意:由于GIF图像是由多幅图像组成,如果想显示可运动的GIF图像就必需绘制出每幅图像。
(7)处理视图类的WM_CREATE消息,在视图窗口创建后开始一个计时器。
int CShowGIFView::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
 if (CView::OnCreate(lpCreateStruct) == -1)   //调用父类的放阿凡
  return -1;
 SetTimer(0,delay*10,NULL);      //开始一个计时器
 return 0;
}
(8)在视图类的析构函数中卸载GDI+。
CShowGIFView::~CShowGIFView()
{
 GdiplusShutdown(m_pGdiToken);     //释放GDI+
}
(9)运行程序,效果如图1所示。
 
图1  显示GIF图像

 

本帖赏分:0 分   回复数:0 篇     
修改   删除   引用   回复
该帖暂无回复!
吉林省明日科技有限公司提供技术支持. 
Copyright © 1999-2008 吉林省明日科技有限公司. 吉ICP备10002740
当前时区 GMT+8, 今天是 
刷新页面 - 关于我们 - 设为首页