作为GDI的升级版本的GDI+实在是个好东西,以前要播放GIF什么的,要引入其他辅助库,或者自己写GIF的读取过程。不过有了GDI+,这些事情都不必再操心了。
在GDI+的设计中,IMAGE本来就是分页、分帧的;可以说,GDI+的IMAGE的设计,本身就是考虑到了几乎目前所有主流图片格式的共性而设计出来的。废话不多说,贴上代码,看GDI+是如何播放GIF的
首先是GIF的载入:
void CGIFControl::Load(LPCTSTR sFileName)
{
m_pImage = new Image(sFileName);
UINT count = m_pImage->GetFrameDimensionsCount();
m_pDimensionIDs =new GUID[count];
m_pImage->GetFrameDimensionsList(m_pDimensionIDs, count);
WCHAR strGuid[39];
StringFromGUID2(m_pDimensionIDs[0], strGuid, 39);
m_FrameCount = m_pImage->GetFrameCount(&m_pDimensionIDs[0]);
//PropertyTagFrameDelay是GDI+中预定义的一个GIG属性ID值,表示标签帧数据的延迟时间
UINT TotalBuffer = m_pImage->GetPropertyItemSize(PropertyTagFrameDelay);
m_pItem = (PropertyItem*)malloc(TotalBuffer);
m_pImage->GetPropertyItem(PropertyTagFrameDelay,TotalBuffer,m_pItem);
}
接着给出播放的代码,值得注意的是,播放我选择了使用WM_TIMER消息,而不是像有些(还比较主流)开源的GIF播放库那样,单独开一个线程来播放,主要是没必要开线程,系统复杂度还高一些(个人意见)。需要注意的一点就是,绘制GIF帧之前,需要用SelectActiveFrame把那个帧设置为当前绘制的帧。
void CGIFControl::OnTimer(UINT_PTR nIDEvent)
{
KillTimer(nIDEvent);
GUID Guid = FrameDimensionTime;
m_pImage->SelectActiveFrame(&Guid,m_iCurrentFrame);
SetTimer(1,((UINT*)m_pItem[0].value)[m_iCurrentFrame] * 10,NULL);
m_iCurrentFrame = (++ m_iCurrentFrame) % m_FrameCount;
Invalidate(FALSE);
}
绘制的代码不多说了,地球人都知道
Graphics g(lpDrawItemStruct->hDC);
DrawBorder(g);
CRect rcClient;
GetClientRect(&rcClient);
if(m_bBorderEnable)
{
rcClient.DeflateRect(m_iBorderLineWidth,m_iBorderLineWidth,m_iBorderLineWidth,m_iBorderLineWidth);
}
g.DrawImage(m_pImage,rcClient.left,rcClient.top,rcClient.Width(),rcClient.Height());
好了,就这么多。