一个简单的能显示动态图片的类(一)
2005-02-22 16:05
429 查看
使用MS的GDI+可以大大的简化图形程序的开发。在VC6中,使用GDI+需要把GDI+头文件,LIB文件,和GDIPLUS.DLL文件,把头文件复制到VC的INCLUDE目录下,把LIB文件复制到VC的LIB目录下,然后再把GDIPLUS.DLL复制到系统目录下(XPSP2和2003已经自带了,不用复制),在代码中使用GDI+前,应该包含头文件,链接LIB文件,一般在MFC工程的StdAfx.h中加入如下几行代码就行:
#ifndef ULONG_PTR
#define ULONG_PTR unsigned long*
#endif
#pragma comment(lib,"gdiplus.lib")
#include <gdiplus.h>
using namespace Gdiplus;
在应用程序初始化和退出的时候,应该初始化和关闭GDI+库,有两个函数可以用:
GdiplusStartupInput m_gdiplusStartupInput;
ULONG_PTR m_gdiplusToken;
GdiplusStartup(&m_gdiplusToken, &m_gdiplusStartupInput, NULL);//初始化
GdiplusShutdown(m_gdiplusToken);//关闭
下面是一个我自己写的能显示动态和静态图片的类,写此类的目的只是学习GDI+的使用,所以写得非常的简单,功能也少,只提供了三个接口。类定义如下:
文件名为ImageEx.h
class ImageEx : public Image
{
public:
ImageEx(const WCHAR* filename, BOOL useEmbeddedColorManagement = FALSE);
~ImageEx();
public:
BOOL IsAnimatedGif(); //判断是否是动态GIF文件
long GetFrameTime(); //获取当前帧应该显示的时间长度
void ActiveNextFrame(); //激活下一帧为应该显示的帧
protected:
BOOL TestForAnimatedGIF();
void Initialize();
UINT m_nFrameCount; //帧数
UINT m_nFramePosition; //当前帧的序号
BOOL m_bIsInitialized; //是否初始化完成
PropertyItem* m_pPropertyItem; //属性项,仅用来测试是否是动态图片
};
类的实现如下:
//文件名为ImageEx.cpp
ImageEx::ImageEx(const WCHAR* FileName, BOOL useEmbeddedColorManagement)
:Image(FileName, useEmbeddedColorManagement)
{
Initialize(); //初始化
m_bIsInitialized = true;
TestForAnimatedGIF(); //检查是不是GIF动画
}
ImageEx::~ImageEx()
{
free(m_pPropertyItem);
m_pPropertyItem = NULL;
}
void ImageEx::Initialize()
{
m_nFramePosition = 0;
m_nFrameCount = 0;
m_bIsInitialized = false;
m_pPropertyItem = NULL;
}
BOOL ImageEx::TestForAnimatedGIF()
{
UINT count = 0;
count = GetFrameDimensionsCount(); //获得维数
GUID* pDimensionIDs = new GUID[count]; //分配维ID数组
// Get the list of frame dimensions from the Image object.
GetFrameDimensionsList(pDimensionIDs, count);//获得各维的ID
// Get the number of frames in the first dimension.
m_nFrameCount = GetFrameCount(&pDimensionIDs[0]);//获得第一维的帧数
// Assume that the image has a property item of type PropertyItemEquipMake.
// Get the size of that property item.
int nSize = GetPropertyItemSize(PropertyTagFrameDelay);//获得帧延迟项
// Allocate a buffer to receive the property item.
m_pPropertyItem = (PropertyItem*) malloc(nSize);
GetPropertyItem(PropertyTagFrameDelay, nSize, m_pPropertyItem);
delete pDimensionIDs;
return m_nFrameCount > 1;
}
BOOL ImageEx::IsAnimatedGif()
{
return m_nFrameCount > 1;
}
long ImageEx::GetFrameTime()
{
long lPause = ((long*) m_pPropertyItem->value)[m_nFramePosition] * 10;
return lPause;
}
void ImageEx::ActiveNextFrame()
{
if (IsAnimatedGif() == FALSE)
return;
GUID pageGuid = FrameDimensionTime;
SelectActiveFrame(&pageGuid, m_nFramePosition++);
if (m_nFramePosition == m_nFrameCount)
m_nFramePosition = 0;
}
类的使用非常简单,要显示动态的图片,应该用计时器来帮助实现,测试可以在一个对话框类中加入如下成员变量:
ImageEx* m_pImg; //图像
RECT m_ImgRect; //图像区域
UINT m_nTimer; //计时器
对话框的构造函数和析构函数如下:
CImgTestDlg::CImgTestDlg(CWnd* pParent /*=NULL*/)
: CDialog(CImgTestDlg::IDD, pParent)
{
//{{AFX_DATA_INIT(CImgTestDlg)
// NOTE: the ClassWizard will add member initialization here
//}}AFX_DATA_INIT
// Note that LoadIcon does not require a subsequent DestroyIcon in Win32
m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
m_pImg = NULL;
m_nTimer = 0;
}
CImgTestDlg::~CImgTestDlg()
{
if (m_pImg != NULL)
{
delete m_pImg;
m_pImg = NULL;
}
if( m_nTimer != 0)
{
KillTimer(m_nTimer);
}
}
我将在一个Cancel按钮函数中装入图片并显示它,这样,当我们点了Cancel按钮时,将加载指定的图片并显示在我们的对话框中:
void CImgTestDlg::OnCancel()
{
if (m_pImg != NULL)
{
return;
}
m_pImg = new ImageEx(L"gx033.gif");
m_ImgRect.left = 0;
m_ImgRect.top = 0;
m_ImgRect.right = m_pImg->GetWidth();
m_ImgRect.bottom = m_pImg->GetHeight();
if (m_pImg->IsAnimatedGif())
{
long lFrameTime = m_pImg->GetFrameTime();
m_nTimer = SetTimer(1, lFrameTime, NULL);
if (m_nTimer == 0)
{
MessageBox("Timer Null");
return;
}
}
InvalidateRect(&m_ImgRect, FALSE);
}
为了让图片刷新时不闪烁,在这里,我们只刷新图片区域,所以我们不用Invalidate()函数,这样,而且,InvalidateRectt()的第二个参数一定要设置为FALSE,否则,一样会闪烁。
在上面的函数中,我们设置了一个计时器,所以,我们要处理时钟消息,代码如下:
void CImgTestDlg::OnTimer(UINT nIDEvent)
{
// TODO: Add your message handler code here and/or call default
if (m_pImg != NULL)
{
if (!m_pImg->IsAnimatedGif())
{
return;
}
m_pImg->ActiveNextFrame(); //显示下一帧
long lFrameTime = m_pImg->GetFrameTime(); //获得下一帧的显示时间
m_nTimer = SetTimer(1, lFrameTime, NULL); //修改计时器的周期为下一帧的显示时间
InvalidateRect(&m_ImgRect, FALSE); //刷新图片区域
}
CDialog::OnTimer(nIDEvent);
}
为了显示图片,我们在对话框重画的时候必须画上我们的图片,在对话框的OnPait()函数中,我们加入下面的代码:
if (m_pImg != NULL)
{
CClientDC dc(this);
Graphics graphics(dc.m_hDC);
Status sta = graphics.DrawImage(m_pImg, 0, 0);
}
这时,算是完成了,只要点击“取消”按钮,就能画出你指定的图片。效果如下
#ifndef ULONG_PTR
#define ULONG_PTR unsigned long*
#endif
#pragma comment(lib,"gdiplus.lib")
#include <gdiplus.h>
using namespace Gdiplus;
在应用程序初始化和退出的时候,应该初始化和关闭GDI+库,有两个函数可以用:
GdiplusStartupInput m_gdiplusStartupInput;
ULONG_PTR m_gdiplusToken;
GdiplusStartup(&m_gdiplusToken, &m_gdiplusStartupInput, NULL);//初始化
GdiplusShutdown(m_gdiplusToken);//关闭
下面是一个我自己写的能显示动态和静态图片的类,写此类的目的只是学习GDI+的使用,所以写得非常的简单,功能也少,只提供了三个接口。类定义如下:
文件名为ImageEx.h
class ImageEx : public Image
{
public:
ImageEx(const WCHAR* filename, BOOL useEmbeddedColorManagement = FALSE);
~ImageEx();
public:
BOOL IsAnimatedGif(); //判断是否是动态GIF文件
long GetFrameTime(); //获取当前帧应该显示的时间长度
void ActiveNextFrame(); //激活下一帧为应该显示的帧
protected:
BOOL TestForAnimatedGIF();
void Initialize();
UINT m_nFrameCount; //帧数
UINT m_nFramePosition; //当前帧的序号
BOOL m_bIsInitialized; //是否初始化完成
PropertyItem* m_pPropertyItem; //属性项,仅用来测试是否是动态图片
};
类的实现如下:
//文件名为ImageEx.cpp
ImageEx::ImageEx(const WCHAR* FileName, BOOL useEmbeddedColorManagement)
:Image(FileName, useEmbeddedColorManagement)
{
Initialize(); //初始化
m_bIsInitialized = true;
TestForAnimatedGIF(); //检查是不是GIF动画
}
ImageEx::~ImageEx()
{
free(m_pPropertyItem);
m_pPropertyItem = NULL;
}
void ImageEx::Initialize()
{
m_nFramePosition = 0;
m_nFrameCount = 0;
m_bIsInitialized = false;
m_pPropertyItem = NULL;
}
BOOL ImageEx::TestForAnimatedGIF()
{
UINT count = 0;
count = GetFrameDimensionsCount(); //获得维数
GUID* pDimensionIDs = new GUID[count]; //分配维ID数组
// Get the list of frame dimensions from the Image object.
GetFrameDimensionsList(pDimensionIDs, count);//获得各维的ID
// Get the number of frames in the first dimension.
m_nFrameCount = GetFrameCount(&pDimensionIDs[0]);//获得第一维的帧数
// Assume that the image has a property item of type PropertyItemEquipMake.
// Get the size of that property item.
int nSize = GetPropertyItemSize(PropertyTagFrameDelay);//获得帧延迟项
// Allocate a buffer to receive the property item.
m_pPropertyItem = (PropertyItem*) malloc(nSize);
GetPropertyItem(PropertyTagFrameDelay, nSize, m_pPropertyItem);
delete pDimensionIDs;
return m_nFrameCount > 1;
}
BOOL ImageEx::IsAnimatedGif()
{
return m_nFrameCount > 1;
}
long ImageEx::GetFrameTime()
{
long lPause = ((long*) m_pPropertyItem->value)[m_nFramePosition] * 10;
return lPause;
}
void ImageEx::ActiveNextFrame()
{
if (IsAnimatedGif() == FALSE)
return;
GUID pageGuid = FrameDimensionTime;
SelectActiveFrame(&pageGuid, m_nFramePosition++);
if (m_nFramePosition == m_nFrameCount)
m_nFramePosition = 0;
}
类的使用非常简单,要显示动态的图片,应该用计时器来帮助实现,测试可以在一个对话框类中加入如下成员变量:
ImageEx* m_pImg; //图像
RECT m_ImgRect; //图像区域
UINT m_nTimer; //计时器
对话框的构造函数和析构函数如下:
CImgTestDlg::CImgTestDlg(CWnd* pParent /*=NULL*/)
: CDialog(CImgTestDlg::IDD, pParent)
{
//{{AFX_DATA_INIT(CImgTestDlg)
// NOTE: the ClassWizard will add member initialization here
//}}AFX_DATA_INIT
// Note that LoadIcon does not require a subsequent DestroyIcon in Win32
m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
m_pImg = NULL;
m_nTimer = 0;
}
CImgTestDlg::~CImgTestDlg()
{
if (m_pImg != NULL)
{
delete m_pImg;
m_pImg = NULL;
}
if( m_nTimer != 0)
{
KillTimer(m_nTimer);
}
}
我将在一个Cancel按钮函数中装入图片并显示它,这样,当我们点了Cancel按钮时,将加载指定的图片并显示在我们的对话框中:
void CImgTestDlg::OnCancel()
{
if (m_pImg != NULL)
{
return;
}
m_pImg = new ImageEx(L"gx033.gif");
m_ImgRect.left = 0;
m_ImgRect.top = 0;
m_ImgRect.right = m_pImg->GetWidth();
m_ImgRect.bottom = m_pImg->GetHeight();
if (m_pImg->IsAnimatedGif())
{
long lFrameTime = m_pImg->GetFrameTime();
m_nTimer = SetTimer(1, lFrameTime, NULL);
if (m_nTimer == 0)
{
MessageBox("Timer Null");
return;
}
}
InvalidateRect(&m_ImgRect, FALSE);
}
为了让图片刷新时不闪烁,在这里,我们只刷新图片区域,所以我们不用Invalidate()函数,这样,而且,InvalidateRectt()的第二个参数一定要设置为FALSE,否则,一样会闪烁。
在上面的函数中,我们设置了一个计时器,所以,我们要处理时钟消息,代码如下:
void CImgTestDlg::OnTimer(UINT nIDEvent)
{
// TODO: Add your message handler code here and/or call default
if (m_pImg != NULL)
{
if (!m_pImg->IsAnimatedGif())
{
return;
}
m_pImg->ActiveNextFrame(); //显示下一帧
long lFrameTime = m_pImg->GetFrameTime(); //获得下一帧的显示时间
m_nTimer = SetTimer(1, lFrameTime, NULL); //修改计时器的周期为下一帧的显示时间
InvalidateRect(&m_ImgRect, FALSE); //刷新图片区域
}
CDialog::OnTimer(nIDEvent);
}
为了显示图片,我们在对话框重画的时候必须画上我们的图片,在对话框的OnPait()函数中,我们加入下面的代码:
if (m_pImg != NULL)
{
CClientDC dc(this);
Graphics graphics(dc.m_hDC);
Status sta = graphics.DrawImage(m_pImg, 0, 0);
}
这时,算是完成了,只要点击“取消”按钮,就能画出你指定的图片。效果如下
相关文章推荐
- 一个最简单的sdl显示图片例子sdl example sdl 例子 例程SDL贴图bmp
- VS2010配置opencv2.4.8,用MFC创建显示一个图片的简单程序
- AsyncTask 的简单使用,给定一个uri地址下载图片,并显示进度条
- Java之简单的图片动态显示(实现类似GIF动画效果)
- 自学笔记:一个简单的神经网络,机器学习数字图片,可以显示错误的数字的图片
- 一个简单的动态显示层
- GridView的最后固定显示一个增加图片,点击图片动态增加内容item
- Java之简单的图片动态显示(实现类似GIF动画结果)
- 一个简单的全屏图片上下打开显示网页效果示例
- 一个简单的JavaScript图片显示与隐藏例子
- GridView的最后固定显示一个增加图片,点击图片动态增加内容item
- 用android做的一个简单的点击按钮显示图片的程序
- 一个简单的全屏图片上下打开显示网页效果示例
- 窗体中有一个图片框,显示一副图片。要求:1)在窗体打开时,动态加载图片;2)设置图片显示模式为根据图片框大小缩放图片;3)图片自己找;4)当鼠标停留在图片框时,显示“**风光”提
- php zend Framework 模板显示图片 显示不失败,就一个红叉叉
- 想给自己制作一个简单的相册吗?快来看看 怎样实现3D图片相册效果
- 博计报表动态显示图片实现预警
- 一个ASP.NET母板页图片显示问题
- 使用UIScrollView和UIPageControl实现一个简单的图片浏览功能
- pygame简单动态图 & 动态图片的移动