现在的位置: 首页 > 综合 > 正文

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

2012年08月15日 ⁄ 综合 ⁄ 共 6371字 ⁄ 字号 评论关闭
源码
#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)); 

抱歉!评论已关闭.