diff --git a/DuiLib/Control/UIGifAnim-patch.cpp b/DuiLib/Control/UIGifAnim-patch.cpp new file mode 100644 index 0000000..61aa32f --- /dev/null +++ b/DuiLib/Control/UIGifAnim-patch.cpp @@ -0,0 +1,368 @@ +#include "StdAfx.h" +#include "UIGifAnim.h" + +/////////////////////////////////////////////////////////////////////////////////////// +DECLARE_HANDLE(HZIP); // An HZIP identifies a zip file that has been opened +typedef DWORD ZRESULT; +typedef struct +{ + int index; // index of this file within the zip + char name[MAX_PATH]; // filename within the zip + DWORD attr; // attributes, as in GetFileAttributes. + FILETIME atime,ctime,mtime;// access, create, modify filetimes + long comp_size; // sizes of item, compressed and uncompressed. These + long unc_size; // may be -1 if not yet known (e.g. being streamed in) +} ZIPENTRY; +typedef struct +{ + int index; // index of this file within the zip + TCHAR name[MAX_PATH]; // filename within the zip + DWORD attr; // attributes, as in GetFileAttributes. + FILETIME atime,ctime,mtime;// access, create, modify filetimes + long comp_size; // sizes of item, compressed and uncompressed. These + long unc_size; // may be -1 if not yet known (e.g. being streamed in) +} ZIPENTRYW; +#define OpenZip OpenZipU +#define CloseZip(hz) CloseZipU(hz) +extern HZIP OpenZipU(void *z,unsigned int len,DWORD flags); +extern ZRESULT CloseZipU(HZIP hz); +#ifdef _UNICODE +#define ZIPENTRY ZIPENTRYW +#define GetZipItem GetZipItemW +#define FindZipItem FindZipItemW +#else +#define GetZipItem GetZipItemA +#define FindZipItem FindZipItemA +#endif +extern ZRESULT GetZipItemA(HZIP hz, int index, ZIPENTRY *ze); +extern ZRESULT GetZipItemW(HZIP hz, int index, ZIPENTRYW *ze); +extern ZRESULT FindZipItemA(HZIP hz, const TCHAR *name, bool ic, int *index, ZIPENTRY *ze); +extern ZRESULT FindZipItemW(HZIP hz, const TCHAR *name, bool ic, int *index, ZIPENTRYW *ze); +extern ZRESULT UnzipItem(HZIP hz, int index, void *dst, unsigned int len, DWORD flags); +/////////////////////////////////////////////////////////////////////////////////////// + +namespace DuiLib +{ + + CGifAnimUI::CGifAnimUI(void) + { + m_pGifImage = NULL; + m_pPropertyItem = NULL; + m_nFrameCount = 0; + m_nFramePosition = 0; + m_bIsAutoPlay = true; + m_bIsAutoSize = false; + m_bIsPlaying = false; + m_pStream = NULL; + } + + + CGifAnimUI::~CGifAnimUI(void) + { + DeleteGif(); + m_pManager->KillTimer( this, EVENT_TIEM_ID ); + + } + + LPCTSTR CGifAnimUI::GetClass() const + { + return DUI_CTR_GIFANIM; + } + + LPVOID CGifAnimUI::GetInterface( LPCTSTR pstrName ) + { + if( _tcscmp(pstrName, DUI_CTR_GIFANIM) == 0 ) return static_cast(this); + return CControlUI::GetInterface(pstrName); + } + + void CGifAnimUI::DoInit() + { + InitGifImage(); + } + + bool CGifAnimUI::DoPaint(HDC hDC, const RECT& rcPaint, CControlUI* pStopControl) + { + if ( NULL == m_pGifImage ) + { + InitGifImage(); + } + DrawFrame( hDC ); + return true; + } + + void CGifAnimUI::DoEvent( TEventUI& event ) + { + if( event.Type == UIEVENT_TIMER ) + OnTimer( (UINT_PTR)event.wParam ); + } + + void CGifAnimUI::SetVisible(bool bVisible /* = true */) + { + CControlUI::SetVisible(bVisible); + if (bVisible) + PlayGif(); + else + StopGif(); + } + + void CGifAnimUI::SetAttribute(LPCTSTR pstrName, LPCTSTR pstrValue) + { + if( _tcscmp(pstrName, _T("bkimage")) == 0 ) SetBkImage(pstrValue); + else if( _tcscmp(pstrName, _T("autoplay")) == 0 ) { + SetAutoPlay(_tcscmp(pstrValue, _T("true")) == 0); + } + else if( _tcscmp(pstrName, _T("autosize")) == 0 ) { + SetAutoSize(_tcscmp(pstrValue, _T("true")) == 0); + } + else + CControlUI::SetAttribute(pstrName, pstrValue); + } + + void CGifAnimUI::SetBkImage(LPCTSTR pStrImage) + { + if( m_sBkImage == pStrImage || NULL == pStrImage) return; + + m_sBkImage = pStrImage; + + StopGif(); + DeleteGif(); + + Invalidate(); + + } + + LPCTSTR CGifAnimUI::GetBkImage() + { + return m_sBkImage.GetData(); + } + + void CGifAnimUI::SetAutoPlay(bool bIsAuto) + { + m_bIsAutoPlay = bIsAuto; + } + + bool CGifAnimUI::IsAutoPlay() const + { + return m_bIsAutoPlay; + } + + void CGifAnimUI::SetAutoSize(bool bIsAuto) + { + m_bIsAutoSize = bIsAuto; + } + + bool CGifAnimUI::IsAutoSize() const + { + return m_bIsAutoSize; + } + + void CGifAnimUI::PlayGif() + { + if (m_bIsPlaying || m_pGifImage == NULL) + { + return; + } + + long lPause = ((long*) m_pPropertyItem->value)[m_nFramePosition] * 10; + if ( lPause == 0 ) lPause = 100; + m_pManager->SetTimer( this, EVENT_TIEM_ID, lPause ); + + m_bIsPlaying = true; + } + + void CGifAnimUI::PauseGif() + { + if (!m_bIsPlaying || m_pGifImage == NULL) + { + return; + } + + m_pManager->KillTimer(this, EVENT_TIEM_ID); + this->Invalidate(); + m_bIsPlaying = false; + } + + void CGifAnimUI::StopGif() + { + if (!m_bIsPlaying) + { + return; + } + + m_pManager->KillTimer(this, EVENT_TIEM_ID); + m_nFramePosition = 0; + this->Invalidate(); + m_bIsPlaying = false; + } + + void CGifAnimUI::InitGifImage() + { + m_pGifImage = LoadGifFromFile(GetBkImage()); + if ( NULL == m_pGifImage ) return; + UINT nCount = 0; + nCount = m_pGifImage->GetFrameDimensionsCount(); + GUID* pDimensionIDs = new GUID[ nCount ]; + m_pGifImage->GetFrameDimensionsList( pDimensionIDs, nCount ); + m_nFrameCount = m_pGifImage->GetFrameCount( &pDimensionIDs[0] ); + int nSize = m_pGifImage->GetPropertyItemSize( PropertyTagFrameDelay ); + m_pPropertyItem = (Gdiplus::PropertyItem*) malloc( nSize ); + m_pGifImage->GetPropertyItem( PropertyTagFrameDelay, nSize, m_pPropertyItem ); + delete[] pDimensionIDs; + pDimensionIDs = NULL; + + if (m_bIsAutoSize) + { + SetFixedWidth(m_pGifImage->GetWidth()); + SetFixedHeight(m_pGifImage->GetHeight()); + } + if (m_bIsAutoPlay && nSize > 0) + { + PlayGif(); + } + } + + void CGifAnimUI::DeleteGif() + { + if (m_pStream != NULL ) + { + m_pStream->Release(); + m_pStream = NULL; + } + if ( m_pGifImage != NULL ) + { + delete m_pGifImage; + m_pGifImage = NULL; + } + + if ( m_pPropertyItem != NULL ) + { + free( m_pPropertyItem ); + m_pPropertyItem = NULL; + } + m_nFrameCount = 0; + m_nFramePosition = 0; + } + + void CGifAnimUI::OnTimer( UINT_PTR idEvent ) + { + if ( idEvent != EVENT_TIEM_ID ) + return; + m_pManager->KillTimer( this, EVENT_TIEM_ID ); + this->Invalidate(); + + m_nFramePosition = (++m_nFramePosition) % m_nFrameCount; + + long lPause = ((long*) m_pPropertyItem->value)[m_nFramePosition] * 10; + if ( lPause == 0 ) lPause = 100; + m_pManager->SetTimer( this, EVENT_TIEM_ID, lPause ); + } + + void CGifAnimUI::DrawFrame( HDC hDC ) + { + if ( NULL == hDC || NULL == m_pGifImage ) return; + GUID pageGuid = Gdiplus::FrameDimensionTime; + Gdiplus::Graphics graphics( hDC ); + graphics.DrawImage( m_pGifImage, m_rcItem.left, m_rcItem.top, m_rcItem.right-m_rcItem.left, m_rcItem.bottom-m_rcItem.top ); + m_pGifImage->SelectActiveFrame( &pageGuid, m_nFramePosition ); + } + + Gdiplus::Image* CGifAnimUI::LoadGifFromFile(LPCTSTR pstrGifPath) + { + LPBYTE pData = NULL; + DWORD dwSize = 0; + + do + { + CDuiString sFile = CPaintManagerUI::GetResourcePath(); + if( CPaintManagerUI::GetResourceZip().IsEmpty() ) { + sFile += pstrGifPath; + HANDLE hFile = ::CreateFile(sFile.GetData(), GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, \ + FILE_ATTRIBUTE_NORMAL, NULL); + if( hFile == INVALID_HANDLE_VALUE ) break; + dwSize = ::GetFileSize(hFile, NULL); + if( dwSize == 0 ) break; + + DWORD dwRead = 0; + pData = new BYTE[ dwSize ]; + ::ReadFile( hFile, pData, dwSize, &dwRead, NULL ); + ::CloseHandle( hFile ); + + if( dwRead != dwSize ) { + delete[] pData; + pData = NULL; + break; + } + } + else { + sFile += CPaintManagerUI::GetResourceZip(); + HZIP hz = NULL; + if( CPaintManagerUI::IsCachedResourceZip() ) hz = (HZIP)CPaintManagerUI::GetResourceZipHandle(); + else hz = OpenZip((void*)sFile.GetData(), 0, 2); + if( hz == NULL ) break; + ZIPENTRY ze; + int i; + if( FindZipItem(hz, pstrGifPath, true, &i, &ze) != 0 ) break; + dwSize = ze.unc_size; + if( dwSize == 0 ) break; + pData = new BYTE[ dwSize ]; + int res = UnzipItem(hz, i, pData, dwSize, 3); + if( res != 0x00000000 && res != 0x00000600) { + delete[] pData; + pData = NULL; + if( !CPaintManagerUI::IsCachedResourceZip() ) CloseZip(hz); + break; + } + if( !CPaintManagerUI::IsCachedResourceZip() ) CloseZip(hz); + } + + } while (0); + + while (!pData) + { + HANDLE hFile = ::CreateFile(pstrGifPath, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, \ + FILE_ATTRIBUTE_NORMAL, NULL); + if( hFile == INVALID_HANDLE_VALUE ) break; + dwSize = ::GetFileSize(hFile, NULL); + if( dwSize == 0 ) break; + + DWORD dwRead = 0; + pData = new BYTE[ dwSize ]; + ::ReadFile( hFile, pData, dwSize, &dwRead, NULL ); + ::CloseHandle( hFile ); + + if( dwRead != dwSize ) { + delete[] pData; + pData = NULL; + } + break; + } + if (!pData) + { + return NULL; + } + + Gdiplus::Image* pImage = LoadGifFromMemory(pData, dwSize); + delete[] pData; + return pImage; + } + + Gdiplus::Image* CGifAnimUI::LoadGifFromMemory( LPVOID pBuf,size_t dwSize ) + { + HGLOBAL hMem = ::GlobalAlloc(GMEM_MOVEABLE, dwSize); + BYTE* pMem = (BYTE*)::GlobalLock(hMem); + + memcpy(pMem, pBuf, dwSize); + ::GlobalUnlock(hMem); + + ::CreateStreamOnHGlobal(hMem, TRUE, &m_pStream); + Gdiplus::Image *pImg = Gdiplus::Image::FromStream(m_pStream); + if(!pImg || pImg->GetLastStatus() != Gdiplus::Ok) + { + m_pStream->Release(); + m_pStream = NULL; + return 0; + } + return pImg; + } + +}