gif.h
class CGIFImage : public CStatic { // Construction public: CGIFImage(); void LoadGIF(WCHAR *); void Pause(); void Resume(); int m_state; // Attributes private: struct _sTHPar { Image *m_Img; PropertyItem *m_item; int m_Count; HWND m_hWnd; }sThPar; Image *m_Img; DWORD m_ThreadId; public: // Operations public: // Overrides // ClassWizard generated virtual function overrides //{{AFX_VIRTUAL(CGIFImage) //}}AFX_VIRTUAL // Implementation public: virtual ~CGIFImage(); // Generated message map functions protected: //{{AFX_MSG(CGIFImage) afx_msg void OnPaint(); //}}AFX_MSG static DWORD WINAPI DrawGIF(LPVOID); DECLARE_MESSAGE_MAP() };
gif.cpp
CGIFImage::CGIFImage() { m_ThreadId=0; m_Img=0; m_state=-1; } CGIFImage::~CGIFImage() { if(m_ThreadId) { ::PostThreadMessage(m_ThreadId,WM_GIFSTOP,0,0); } } BEGIN_MESSAGE_MAP(CGIFImage, CStatic) //{{AFX_MSG_MAP(CGIFImage) ON_WM_PAINT() //}}AFX_MSG_MAP END_MESSAGE_MAP() ///////////////////////////////////////////////////////////////////////////// // CGIFImage message handlers void CGIFImage::OnPaint() { CPaintDC dc(this); // device context for painting // TODO: Add your message handler code here if(m_ThreadId && m_Img) { RECT rWin; GetClientRect(&rWin); RectF rF(rWin.left,rWin.top,rWin.right,rWin.bottom); Graphics gh(dc.m_hDC); gh.DrawImage(m_Img,rF,0,0,m_Img->GetWidth(),m_Img->GetHeight(),UnitPixel); } // Do not call CStatic::OnPaint() for painting messages } void CGIFImage::LoadGIF(WCHAR *wzFile) { if(m_ThreadId) { ::PostThreadMessage(m_ThreadId,WM_GIFSTOP,0,0); } m_Img=Image::FromFile(wzFile,FALSE); UINT count=m_Img->GetFrameDimensionsCount(); GUID *pDimensionIDs=(GUID*)new GUID[count]; m_Img->GetFrameDimensionsList(pDimensionIDs, count); WCHAR strGuid[39]; StringFromGUID2(pDimensionIDs[0], strGuid, 39); UINT frameCount=m_Img->GetFrameCount(&pDimensionIDs[0]); delete []pDimensionIDs; UINT FrameDelayNums=m_Img->GetPropertyItemSize(PropertyTagFrameDelay); PropertyItem * lpPropertyItem=new PropertyItem[FrameDelayNums]; m_Img->GetPropertyItem(PropertyTagFrameDelay,FrameDelayNums,lpPropertyItem); _sTHPar *sP=new _sTHPar ; sP->m_hWnd=m_hWnd; sP->m_Img=m_Img; sP->m_Count=frameCount; sP->m_item=lpPropertyItem; CreateThread(0,0,DrawGIF,sP,0,&m_ThreadId); m_state=1; } DWORD WINAPI CGIFImage::DrawGIF(LPVOID l) { _sTHPar *par=(_sTHPar*)l; int FrameCount=0; long lPause=0; HDC dc=::GetWindowDC(par->m_hWnd); RECT rWin; ::GetClientRect(par->m_hWnd,&rWin); RectF rF(rWin.left,rWin.top,rWin.right,rWin.bottom); GUID Guid = FrameDimensionTime; par->m_Img->SelectActiveFrame(&Guid,FrameCount); Graphics gh(dc); gh.DrawImage(par->m_Img,rF,0,0,par->m_Img->GetWidth(),par->m_Img->GetHeight(),UnitPixel); DWORD dTick=GetTickCount(); lPause = ((long*)par->m_item->value)[FrameCount]*10; while(1) { Sleep(1); MSG msg; if(PeekMessage(&msg,0,0,0,PM_REMOVE)) { if(msg.message==WM_GIFSTOP) { ::ReleaseDC(par->m_hWnd,dc); delete par->m_Img; delete[] par->m_item; delete par; return 0; } } else { if(par->m_Count>1) { if(GetTickCount()-dTick>=lPause) { if ((FrameCount+1)==par->m_Count) { FrameCount=0; par->m_Img->SelectActiveFrame(&Guid,0); } else { par->m_Img->SelectActiveFrame(&Guid,++FrameCount); } Graphics gh(dc); gh.DrawImage(par->m_Img,rF,0,0,par->m_Img->GetWidth(),par->m_Img->GetHeight(),UnitPixel); lPause = ((long*)par->m_item->value)[FrameCount]*10; dTick=GetTickCount(); } } } } return 0; } void CGIFImage::Pause() { if(m_ThreadId) { typedef HANDLE (WINAPI *OPENTHREAD) (DWORD , BOOL , DWORD ); OPENTHREAD lpfnOpenThread = (OPENTHREAD)GetProcAddress(LoadLibrary("kernel32.dll"),"OpenThread"); HANDLE hThread = lpfnOpenThread(THREAD_ALL_ACCESS, FALSE, m_ThreadId); SuspendThread(hThread); m_state=0; } } void CGIFImage::Resume() { if(m_ThreadId) { typedef HANDLE (WINAPI *OPENTHREAD) (DWORD , BOOL , DWORD ); OPENTHREAD lpfnOpenThread = (OPENTHREAD)GetProcAddress(LoadLibrary("kernel32.dll"),"OpenThread"); HANDLE hThread = lpfnOpenThread(THREAD_ALL_ACCESS, FALSE, m_ThreadId); ResumeThread(hThread); m_state=1; } }