www.gusucode.com > 用VS2008+ATL开发可以显示Gif的ActiveX控件源码源码程序 > 用VS2008+ATL开发可以显示Gif的ActiveX控件源码/用VS2008+ATL开发Gif的ActiveX控件/用VS2008+ATL开发Gif的ActiveX控件/GifSolution/GifAnimate/GifImage.cpp
#include "StdAfx.h" #include "GifImage.h" GifImage::GifImage(void) { m_hDestHwnd = NULL; m_hThread = NULL; reset_status(); } GifImage::~GifImage(void) { free_gif(); } void GifImage::reset_status() { m_Direction = emForward; m_dDelayTimeFactor = 1.0; m_nLoop = -1; m_nFrameCount = 0; m_nCurrentFrame = -1; m_bStopFlag = false; m_bPlaying = false; } //加载文件 bool GifImage::LoadGifFromFile(BSTR bstrFile) { free_gif(); SharedPtr<Image> pImage(new Image(bstrFile)); if (pImage->GetLastStatus() != Ok) return false; return load_gif(pImage); } bool GifImage::LoadGifFromStream(IUnknown* pStream) { free_gif(); CComQIPtr<IStream> pTemp = pStream; if (pTemp == NULL) return false; SharedPtr<Image> pImage(new Image((IStream*)pTemp)); if (pImage->GetLastStatus() != Ok) return false; return load_gif(pImage); } bool GifImage::load_gif(SharedPtr<Image>& pImage) { m_image = pImage; if (m_image == NULL) return false; // How many frame dimensions does the Image object have? int nCount = m_image->GetFrameDimensionsCount(); if (nCount <= 0) return false; // Get the list of frame dimensions from the Image object. SharedPtr<GUID> pDimensionGUIDs(new GUID[nCount], true); if (Ok != m_image->GetFrameDimensionsList(pDimensionGUIDs.GetInternalPtr(), nCount)) return false; // Display the GUID of the first (and only) frame dimension. // Get the number of frames in the first dimension. WCHAR strGuid[39] = {0}; StringFromGUID2(pDimensionGUIDs.GetInternalPtr()[0], strGuid, 39); m_nFrameCount = m_image->GetFrameCount(pDimensionGUIDs.GetInternalPtr()); // Assume that the image has a property item of type PropertyTagFrameDelay. // Get the size of that property item. int nSize = m_image->GetPropertyItemSize(PropertyTagFrameDelay); if (nSize > 0) { // Allocate a buffer to receive the property item. m_pDelay = SharedPtr<PropertyItem>((PropertyItem*)malloc(nSize), -1); if (m_pDelay) { m_image->GetPropertyItem(PropertyTagFrameDelay, nSize, m_pDelay.GetInternalPtr()); } } return true; } void GifImage::free_gif() { Stop(); reset_status(); m_image._Release(); m_pDelay._Release(); } //播放 void GifImage::Play(void) { if (m_hThread) { Continue(); } else { DWORD dwThreadID; m_hThread = CreateThread(NULL, 0, &GifThreadProc, this, CREATE_SUSPENDED, &dwThreadID); if (m_hThread) { m_bPlaying = true; ResumeThread(m_hThread); } } } void GifImage::Stop(void) { if (m_hThread) { m_bStopFlag = true; Continue(); if (WAIT_OBJECT_0 == WaitForSingleObject(m_hThread, INFINITE)) { clear_thread(); } } } void GifImage::clear_thread() { m_ClearLock.Lock(); if (m_hThread) { CloseHandle(m_hThread); m_hThread = NULL; } m_bPlaying = false; m_bStopFlag = false; m_ClearLock.Unlock(); } void GifImage::Pause(void) { if (m_hThread && m_bPlaying) { m_bPlaying = false; SuspendThread(m_hThread); } } void GifImage::Continue(void) { if (m_hThread && !m_bPlaying) { m_bPlaying = true; ResumeThread(m_hThread); } } void GifImage::PrevFrame(void) { move_frame(m_Direction == emReverse); } void GifImage::NextFrame(void) { move_frame(m_Direction == emForward); } void GifImage::move_frame(bool bNext) { m_MoveFrameLock.Lock(); if (bNext) ++m_nCurrentFrame; else --m_nCurrentFrame; if (m_nCurrentFrame < 0 || m_nCurrentFrame >= m_nFrameCount) { if (m_nLoop != 0) { if (m_nCurrentFrame >= m_nFrameCount) m_nCurrentFrame = 0; if (m_nCurrentFrame < 0) m_nCurrentFrame = m_nFrameCount - 1; } if (m_nLoop > 0) { --m_nLoop; } } m_MoveFrameLock.Unlock(); } DWORD WINAPI GifThreadProc(LPVOID lpParameter) { if (lpParameter == NULL) { ATLASSERT(FALSE); return 0; } GifImage* pGif = (GifImage*)lpParameter; if (!pGif->m_image) { pGif->clear_thread(); return 0; } Graphics gp(pGif->m_hDestHwnd); UINT nWidth = pGif->m_image->GetWidth(); UINT nHeight = pGif->m_image->GetHeight(); while (true) { if (pGif->m_bStopFlag) break; if (!::IsWindow(pGif->m_hDestHwnd)) { Sleep(500); continue; } pGif->NextFrame(); if (pGif->m_nCurrentFrame < 0 || pGif->m_nCurrentFrame >= pGif->m_nFrameCount) break; pGif->m_image->SelectActiveFrame(&FrameDimensionTime, pGif->m_nCurrentFrame); gp.DrawImage(pGif->m_image.GetInternalPtr(), 0, 0, nWidth, nHeight); if (pGif->m_pDelay) Sleep(((long*)pGif->m_pDelay->value)[pGif->m_nCurrentFrame] * 10 * pGif->m_dDelayTimeFactor); else Sleep(100 * pGif->m_dDelayTimeFactor); } pGif->clear_thread(); return 0; }