gif.h
[cpp]
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
[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;
}
}