用GDI+顯示GIF動畫的一個類

來源:互聯網
上載者:User
源碼
#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)); 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.