Click here to Skip to main content
15,881,882 members
Articles / Desktop Programming / MFC

Play GIF using GDI+

Rate me:
Please Sign up or sign in to vote.
3.34/5 (22 votes)
1 Sep 2011CPOL 77.7K   3.9K   59   17
A new choice for playing GIF using GDI+

Introduction

In the past, there was no convenient enough way to play GIF using functions provided by Microsoft Windows but you may need a reference of 3rd libs. Well, now we have an alternative choice from using GDI+

Base of GDI+

First of all, you need to include GDI+ headers, link the libs and using the namespace. In my sample, I did it in stdafx.h.

C++
//GDI+ references
#include<gdiplus.h />
using namespace Gdiplus;
#pragma comment(lib,"gdiplus.lib")

Before using GDI+ in your application, you should initialize the enviroment code below:

C++
//Init GDI+
GdiplusStartupInput gdiplusStartupInput;
ULONG_PTR gdiplusToken;
Status state = GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);

Correspondent to initialize, you should clean up the environment.

C++
GdiplusShutdown(gdiplusToken);

Critical Code

C++
//Here, we load a GIF image file
void CGIFControl::Load(LPCTSTR sFileName)
{
	m_pImage = new Image(sFileName);
	
	//First of all we should get the number of frame dimensions
	//Images considered by GDI+ as:
	//frames[animation_frame_index][how_many_animation];
	UINT count = m_pImage->GetFrameDimensionsCount();

	//Now we should get the identifiers for the frame dimensions 
	m_pDimensionIDs =new GUID[count];
	m_pImage->GetFrameDimensionsList(m_pDimensionIDs, count);
	
	//For gif image , we only care about animation set#0
	WCHAR strGuid[39];
	StringFromGUID2(m_pDimensionIDs[0], strGuid, 39);
	m_FrameCount = m_pImage->GetFrameCount(&m_pDimensionIDs[0]);

	//PropertyTagFrameDelay is a pre-defined identifier 
	//to present frame-delays by GDI+
	UINT TotalBuffer = m_pImage->GetPropertyItemSize(PropertyTagFrameDelay);
	m_pItem = (PropertyItem*)malloc(TotalBuffer);
	m_pImage->GetPropertyItem(PropertyTagFrameDelay,TotalBuffer,m_pItem);
}

//To start play
void CGIFControl::Play()
{
	//Set Current Frame at #0
	m_iCurrentFrame = 0;
	GUID Guid = FrameDimensionTime;
	m_pImage->SelectActiveFrame(&Guid,m_iCurrentFrame);

	//Use Timer
	//NOTE HERE: frame-delay values should be multiply by 10
	SetTimer(1,((UINT*)m_pItem[0].value)[m_iCurrentFrame]  * 10,NULL);

	//Move to the next frame
	++ m_iCurrentFrame;
	Invalidate(FALSE);
}

//Using timer
void CGIFControl::OnTimer(UINT_PTR nIDEvent)
{
	//Because there will be a new delay value
	KillTimer(nIDEvent);

	//Change Active frame
	GUID Guid = FrameDimensionTime;
	m_pImage->SelectActiveFrame(&Guid,m_iCurrentFrame);

	//New timer
	SetTimer(1,((UINT*)m_pItem[0].value)[m_iCurrentFrame] * 10,NULL);

	//Again move to the next
	m_iCurrentFrame = (++ m_iCurrentFrame) % m_FrameCount;
	Invalidate(FALSE);
}

//Present current frame
void CGIFControl::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct)
{
	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());
}

Using the Code

Step 1: Set control correspondence in DoDataExchange method of sample dialog:

C++
DDX_Control(pDX,IDC_GIF_PLAY,m_Gif);

Step 2: Load the gif image in OnInitDialog:

C++
m_Gif.Load(_T("Sample.gif"));

Finally, add start and finish code in button event handler:

C++
void CGifControlSampleDlg::OnBnClickedBtnPlay()
{
	m_Gif.Play();
}

void CGifControlSampleDlg::OnBnClickedBtnStop()
{
	m_Gif.Stop();
}

About the Source

Binary files in attachment archive are compiled by VS2005SP1, so you may need to install the suit vcredist package by yourself first.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
China China
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
AnswerRe: same code Pin
Yi Li31-Aug-11 21:54
Yi Li31-Aug-11 21:54 
Questionvery bad doku Pin
merano23-Aug-11 6:50
merano23-Aug-11 6:50 
AnswerRe: very bad doku Pin
Yi Li31-Aug-11 22:01
Yi Li31-Aug-11 22:01 
GeneralJust a suggestion Pin
sandeepkavade19-Nov-08 18:38
sandeepkavade19-Nov-08 18:38 
GeneralRe: Just a suggestion Pin
Yi Li6-Sep-11 6:33
Yi Li6-Sep-11 6:33 
GeneralWhich Library Pin
Dileep.M1-Jul-08 2:04
Dileep.M1-Jul-08 2:04 
GeneralRe: Which Library Pin
Yi Li1-Jul-08 17:14
Yi Li1-Jul-08 17:14 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.