Skip to content

Commit

Permalink
增强gif控件
Browse files Browse the repository at this point in the history
1、gif控件增加自动设置大小的属性;
2、修改gif加载资源的方式,现在可以从ZIP资源加载gif
3、RichEdit控件增加设置最长文本的maxchar属性
  • Loading branch information
redrains committed Jan 8, 2015
1 parent 10beab2 commit c986bdb
Show file tree
Hide file tree
Showing 25 changed files with 447 additions and 62 deletions.
233 changes: 205 additions & 28 deletions DuiLib/Control/UIGifAnim.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,46 @@
#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
{

Expand All @@ -11,6 +51,7 @@ namespace DuiLib
m_nFrameCount = 0;
m_nFramePosition = 0;
m_bIsAutoPlay = true;
m_bIsAutoSize = false;
m_bIsPlaying = false;

}
Expand All @@ -31,7 +72,7 @@ namespace DuiLib
LPVOID CGifAnimUI::GetInterface( LPCTSTR pstrName )
{
if( _tcscmp(pstrName, DUI_CTR_GIFANIM) == 0 ) return static_cast<CGifAnimUI*>(this);
return CLabelUI::GetInterface(pstrName);
return CControlUI::GetInterface(pstrName);
}

void CGifAnimUI::DoPaint( HDC hDC, const RECT& rcPaint )
Expand All @@ -52,7 +93,7 @@ namespace DuiLib

void CGifAnimUI::SetVisible(bool bVisible /* = true */)
{
CLabelUI::SetVisible(bVisible);
CControlUI::SetVisible(bVisible);
if (bVisible)
PlayGif();
else
Expand All @@ -61,11 +102,33 @@ namespace DuiLib

void CGifAnimUI::SetAttribute(LPCTSTR pstrName, LPCTSTR pstrValue)
{
if( _tcscmp(pstrName, _T("autoplay")) == 0 ) {
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
CLabelUI::SetAttribute(pstrName, pstrValue);
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)
Expand All @@ -78,6 +141,16 @@ namespace DuiLib
return m_bIsAutoPlay;
}

void CGifAnimUI::SetAutoSize(bool bIsAuto)
{
m_bIsAutoSize = bIsAuto;
}

bool CGifAnimUI::IsAutoSize() const
{
return m_bIsAutoSize;
}

void CGifAnimUI::PlayGif()
{
if (m_bIsPlaying)
Expand Down Expand Up @@ -119,11 +192,12 @@ namespace DuiLib

void CGifAnimUI::InitGifImage()
{
CDuiString sImageName = GetBkImage();
CDuiString sImagePath = CPaintManagerUI::GetResourcePath();
sImagePath += sImageName;
if ( NULL == sImagePath ) return;
m_pGifImage = Gdiplus::Image::FromFile( sImagePath );
// CDuiString sImageName = GetBkImage();
// CDuiString sImagePath = CPaintManagerUI::GetResourcePath();
// sImagePath += sImageName;
// if ( NULL == sImagePath ) return;
// m_pGifImage = Gdiplus::Image::FromFile( sImagePath );
m_pGifImage = LoadGifFromFile(GetBkImage());
if ( NULL == m_pGifImage ) return;
UINT nCount = 0;
nCount = m_pGifImage->GetFrameDimensionsCount();
Expand All @@ -136,6 +210,11 @@ namespace DuiLib
delete pDimensionIDs;
pDimensionIDs = NULL;

if (m_bIsAutoSize)
{
SetFixedWidth(m_pGifImage->GetWidth());
SetFixedHeight(m_pGifImage->GetHeight());
}
if (m_bIsAutoPlay)
{
PlayGif();
Expand All @@ -159,28 +238,126 @@ namespace DuiLib
m_nFramePosition = 0;
}

void CGifAnimUI::OnTimer( UINT_PTR idEvent )
{
if ( idEvent != EVENT_TIEM_ID )
return;
m_pManager->KillTimer( this, EVENT_TIEM_ID );
this->Invalidate();

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 );
}

m_nFramePosition = (++m_nFramePosition) % m_nFrameCount;
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 );
}

long lPause = ((long*) m_pPropertyItem->value)[m_nFramePosition] * 10;
if ( lPause == 0 ) lPause = 100;
m_pManager->SetTimer( this, EVENT_TIEM_ID, lPause );
}
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)
{
//读不到图片, 则直接去读取bitmap.m_lpstr指向的路径
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;
}

return LoadGifFromMemory(pData, dwSize);
}

Gdiplus::Image* CGifAnimUI::LoadGifFromMemory( LPVOID pBuf,size_t dwSize )
{
HGLOBAL hMem = ::GlobalAlloc(GMEM_FIXED, dwSize);
BYTE* pMem = (BYTE*)::GlobalLock(hMem);

memcpy(pMem, pBuf, dwSize);

IStream* pStm = NULL;
::CreateStreamOnHGlobal(hMem, TRUE, &pStm);
Gdiplus::Image *pImg = Gdiplus::Image::FromStream(pStm);
if(!pImg || pImg->GetLastStatus() != Gdiplus::Ok)
{
pStm->Release();
::GlobalUnlock(hMem);
return 0;
}
return pImg;
}

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 );
}

}
14 changes: 12 additions & 2 deletions DuiLib/Control/UIGifAnim.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,11 @@

namespace DuiLib
{
class CLabelUI;
class CControl;

#define EVENT_TIEM_ID 100

class UILIB_API CGifAnimUI : public CLabelUI
class UILIB_API CGifAnimUI : public CControlUI
{
public:
CGifAnimUI(void);
Expand All @@ -21,8 +21,13 @@ namespace DuiLib
void DoEvent(TEventUI& event) override;
void SetVisible(bool bVisible = true ) override;
void SetAttribute(LPCTSTR pstrName, LPCTSTR pstrValue) override;
void SetBkImage(LPCTSTR pStrImage);
LPCTSTR GetBkImage();

void SetAutoPlay(bool bIsAuto = true );
bool IsAutoPlay() const;
void SetAutoSize(bool bIsAuto = true );
bool IsAutoSize() const;
void PlayGif();
void PauseGif();
void StopGif();
Expand All @@ -32,12 +37,17 @@ namespace DuiLib
void DeleteGif();
void OnTimer( UINT_PTR idEvent );
void DrawFrame( HDC hDC ); // 绘制GIF每帧
Gdiplus::Image* LoadGifFromFile(LPCTSTR pstrGifPath);
Gdiplus::Image* LoadGifFromMemory( LPVOID pBuf,size_t dwSize );
private:
Gdiplus::Image *m_pGifImage;
UINT m_nFrameCount; // gif图片总帧数
UINT m_nFramePosition; // 当前放到第几帧
Gdiplus::PropertyItem* m_pPropertyItem; // 帧与帧之间间隔时间

CDuiString m_sBkImage;
bool m_bIsAutoPlay; // 是否自动播放gif
bool m_bIsAutoSize; // 是否自动根据图片设置大小
bool m_bIsPlaying;

};
Expand Down
1 change: 1 addition & 0 deletions DuiLib/Control/UIRichEdit.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2408,6 +2408,7 @@ void CRichEditUI::SetAttribute(LPCTSTR pstrName, LPCTSTR pstrValue)
DWORD clrColor = _tcstoul(pstrValue, &pstr, 16);
SetTextColor(clrColor);
}
else if( _tcscmp(pstrName, _T("maxchar")) == 0 ) SetLimitText(_ttoi(pstrValue));
else if( _tcscmp(pstrName, _T("normalimage")) == 0 ) SetNormalImage(pstrValue);
else if( _tcscmp(pstrName, _T("hotimage")) == 0 ) SetHotImage(pstrValue);
else if( _tcscmp(pstrName, _T("focusedimage")) == 0 ) SetFocusedImage(pstrValue);
Expand Down
7 changes: 6 additions & 1 deletion Duilib和UIlib更新日志.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,9 @@
2015-1-1
2015-1-8
GifAnim�ؼ�����autosize���Կ����Զ����ô�С
GifAnim�޸ļ�����Դ�ķ�ʽ��֧�ִ�zip����
richedit��������ַ���������maxchar

2015-1-7
edit�ؼ��Զ��ж��Ƿ�Ϊ͸�����壬��ѡ�񴴽���ʽ������Ҫ�ֹ�����trans��������Ӧ͸������
richedit�ؼ�����tipvalue��tipvaluecolor����
����GifAnim�ؼ����ɿ���gif�IJ��š���ͣ��ֹͣ
Expand Down
Binary file modified Lib2008/DuiLib_u.lib
Binary file not shown.
Binary file modified Lib2008/DuiLib_ud.lib
Binary file not shown.
Binary file modified Lib2008/UiLib_u.lib
Binary file not shown.
Binary file modified Lib2008/UiLib_ud.lib
Binary file not shown.
Loading

0 comments on commit c986bdb

Please sign in to comment.