您的位置:首页 > 其它

用GDI+显示GIF动画的一个类

2007-11-06 11:45 453 查看
源码
#pragma once

#include <gdiplus.h>
#pragma comment(lib,"gdiplus.lib")
using namespace Gdiplus;

class GIFImage:public Image
{
public:
GIFImage(LPCTSTR sResourceType,LPCTSTR sResource);
GIFImage(const WCHAR *filename,BOOL useEmbeddedColorManagement=FALSE);
~GIFImage();
void GetSize(SIZE *pSize);
bool IsAnimatedGIF() { return m_nFrameCount>1; }
void SetPause(bool bPause);
bool IsPaused() { return m_bPause; }
bool InitAnimation(HWND hWnd,POINT pt);
void ThreadAnimation();
void Destroy();

protected:
bool TestForAnimatedGIF();
void Initialize();
bool DrawFrameGIF();
bool LoadFromBuffer(BYTE* pBuff, int nSize);
bool GetResource(LPCTSTR lpName,LPCTSTR lpType,void *pResource,int &nBufSize);
bool Load(LPCTSTR sResourceType,LPCTSTR sResource);

IStream *m_pStream;
HANDLE m_hThread;
HANDLE m_hPause;
HANDLE m_hExitEvent;
HINSTANCE m_hInst;
HWND m_hWnd;
UINT m_nFrameCount;
UINT m_nFramePosition;
bool m_bIsInitialized;
bool m_bPause;
PropertyItem *m_pPropertyItem;
POINT m_pt;
};

// GDIPlusHelper.cpp: implementation of the CGDIPlusHelper class.
//
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "GIFImage.h"
#include <process.h>

GIFImage::GIFImage(LPCTSTR sResourceType,LPCTSTR sResource)
{
Initialize();
if(Load(sResourceType,sResource))
{
nativeImage=NULL;
lastResult=DllExports::GdipLoadImageFromStreamICM(m_pStream,&nativeImage);
TestForAnimatedGIF();
}
}

GIFImage::GIFImage(const WCHAR *filename,BOOL useEmbeddedColorManagement):Image(filename,useEmbeddedColorManagement)
{
Initialize();
m_bIsInitialized=true;
TestForAnimatedGIF();
}

GIFImage::~GIFImage()
{
Destroy();
}

DWORD WINAPI ThreadAnimationProc(LPVOID pParam)
{
GIFImage *pImage=(GIFImage *)(pParam);
pImage->ThreadAnimation();
return 0;
}

bool GIFImage::InitAnimation(HWND hWnd,POINT pt)
{
m_hWnd=hWnd;
m_pt.x=pt.x;
m_pt.y=pt.y;
if(!m_bIsInitialized)
{
return false;
}
if(IsAnimatedGIF())
{
if(m_hThread==NULL)
{
DWORD nTID=0;
m_hThread=CreateThread(NULL,0,ThreadAnimationProc,this,CREATE_SUSPENDED,&nTID);
if(!m_hThread)
{
return true;
}
else ResumeThread(m_hThread);
}
}
return false;
}

bool GIFImage::LoadFromBuffer(BYTE* pBuff,int nSize)
{
bool bResult=false;
HGLOBAL hGlobal=GlobalAlloc(GMEM_MOVEABLE, nSize);
if(hGlobal)
{
void *pData=GlobalLock(hGlobal);
if(pData) memcpy(pData, pBuff, nSize);
GlobalUnlock(hGlobal);
if(CreateStreamOnHGlobal(hGlobal,TRUE,&m_pStream)==S_OK) bResult=true;
}
return bResult;
}

bool GIFImage::GetResource(LPCTSTR lpName, LPCTSTR lpType,void *pResource, int &nBufSize)
{
HRSRC hResInfo;
HANDLE hRes;
LPSTR lpRes=NULL;
int nLen=0;
bool bResult=FALSE;
//搜寻资源
hResInfo=FindResource(m_hInst,lpName,lpType);
if(hResInfo==NULL)
{
DWORD dwErr=GetLastError();
return false;
}
//加载资源
hRes=LoadResource(m_hInst,hResInfo);
if(hRes==NULL) return false;
//锁定资源
lpRes=(char *)LockResource(hRes);
if(lpRes!=NULL)
{
if(pResource==NULL)
{
nBufSize=SizeofResource(m_hInst , hResInfo);
bResult=true;
}
else
{
if(nBufSize>=(int)SizeofResource(m_hInst,hResInfo))
{
memcpy(pResource,lpRes,nBufSize);
bResult=true;
}
}
UnlockResource(hRes);
}
//释放资源
FreeResource(hRes);
return bResult;
}

bool GIFImage::Load(LPCTSTR sResourceType, LPCTSTR sResource)
{
bool bResult=false;
BYTE *pBuff=NULL;
int nSize=0;
if(GetResource(sResource,sResourceType,pBuff,nSize))
{
if(nSize>0)
{
pBuff=new BYTE[nSize];
if(GetResource(sResource,sResourceType,pBuff,nSize))
{
if(LoadFromBuffer(pBuff, nSize))
{
bResult=true;
}
}
delete []pBuff;
}
}
m_bIsInitialized=bResult;
return bResult;
}

void GIFImage::GetSize(SIZE *pSize)
{
pSize->cx=GetWidth();
pSize->cy=GetHeight();
}

bool GIFImage::TestForAnimatedGIF()
{
UINT count=0;
count=GetFrameDimensionsCount();
GUID *pDimensionIDs=new GUID[count];
//得到帧维数列表
GetFrameDimensionsList(pDimensionIDs,count);
//得到第一个帧维数的帧数
m_nFrameCount=GetFrameCount(&pDimensionIDs[0]);
//得到属性项大小
int nSize = GetPropertyItemSize(PropertyTagFrameDelay);
//为属性项分配缓冲区
m_pPropertyItem=(PropertyItem *)malloc(nSize);
GetPropertyItem(PropertyTagFrameDelay,nSize,m_pPropertyItem);
delete pDimensionIDs;
return m_nFrameCount>1;
}

void GIFImage::Initialize()
{
m_pStream=NULL;
m_nFramePosition=0;
m_nFrameCount=0;
m_pStream=NULL;
lastResult=InvalidParameter;
m_hThread=NULL;
m_bIsInitialized=false;
m_pPropertyItem=NULL;
m_hInst=NULL;
m_bPause=false;
m_hExitEvent=CreateEvent(NULL,TRUE,FALSE,NULL);
m_hPause=CreateEvent(NULL,TRUE,TRUE,NULL);
}

void GIFImage::ThreadAnimation()
{
m_nFramePosition=0;
bool bExit=false;
while(bExit==false)
{
bExit=DrawFrameGIF();
}
}

bool GIFImage::DrawFrameGIF()
{
WaitForSingleObject(m_hPause,INFINITE);
GUID pageGuid=FrameDimensionTime;
long hmWidth=GetWidth();
long hmHeight=GetHeight();
HDC hDC=GetDC(m_hWnd);
if(hDC)
{
Graphics graphics(hDC);
graphics.DrawImage(this,m_pt.x,m_pt.y,hmWidth,hmHeight);
ReleaseDC(m_hWnd,hDC);
}
SelectActiveFrame(&pageGuid,m_nFramePosition++);
if(m_nFramePosition==m_nFrameCount) m_nFramePosition=0;
long lPause=((long *)m_pPropertyItem->value)[m_nFramePosition]*10;
DWORD dwErr=WaitForSingleObject(m_hExitEvent, lPause);
return dwErr==WAIT_OBJECT_0;
}

void GIFImage::SetPause(bool bPause)
{
if(!IsAnimatedGIF()) return;
if(bPause&&!m_bPause)
{
ResetEvent(m_hPause);
}
else
{
if(m_bPause&&!bPause)
{
SetEvent(m_hPause);
}
}
m_bPause=bPause;
}

void GIFImage::Destroy()
{
if(m_hThread)
{
SetPause(false);
SetEvent(m_hExitEvent);
WaitForSingleObject(m_hThread,INFINITE);
}
CloseHandle(m_hThread);
CloseHandle(m_hExitEvent);
CloseHandle(m_hPause);
free(m_pPropertyItem);
m_pPropertyItem=NULL;
m_hThread=NULL;
m_hExitEvent=NULL;
m_hPause=NULL;
if(m_pStream) m_pStream->Release();
}

使用方法
在窗口初始化时添加(你要添加先加Gif图片资源咯"GIF","HEARTS")
GIFImage *m_image;

m_image=new GIFImage("GIF","HEARTS" );
CRect rc;
GetClientRect(rc);
int cx=(rc.Width()-m_image->GetWidth())/2;
m_image->InitAnimation(m_hWnd,CPoint(cx,10));
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: