Click here to Skip to main content
Click here to Skip to main content

Play GIF using GDI+

By , 1 Sep 2011
 

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.

//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:

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

Correspondent to initialize, you should clean up the environment.

GdiplusShutdown(gdiplusToken);

Critical Code

//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:

DDX_Control(pDX,IDC_GIF_PLAY,m_Gif);

Step 2: Load the gif image in OnInitDialog:

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

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

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)

About the Author

Yi Li
China China
Member
No Biography provided

Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
You must Sign In to use this message board.
Search this forum  
    Spacing  Noise  Layout  Per page   
Questionsame codemembermerano23 Aug '11 - 7:26 
This article is a copy:
 
http://www.ucancode.net/Play-GIF-Load-GIF-GIF-Animate-with-GDIPlus-Example.htm#[^]
AnswerRe: same codememberYi Li31 Aug '11 - 21:54 
Thanks for your reply.
 
I've carefully read the given page but I'm afraid the fact is that the article quoted my code because of a keyword "Linabot" in "LinaBot::CommonCtrl::CGIFControl"."Linabot" is a web-based chating bot with "Linabot" as its both project name and code name,and I used the name as a namespace in the project.
 
First version of the attachment code was a part of the project without "making clean",that mean some addtional infomations about the linabot project was provided.I'm very sorry that the version of it can not be compiled directly , but in the next version I'v made it clean and provide a sample project then you can compile it directly.I'v commite the update,and I think the article will be updated in few days).
 
Best regard.

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

Permalink | Advertise | Privacy | Mobile
Web01 | 2.6.130523.1 | Last Updated 1 Sep 2011
Article Copyright 2008 by Yi Li
Everything else Copyright © CodeProject, 1999-2013
Terms of Use
Layout: fixed | fluid