Example 2
Motive
How many of you
developers are using
GDI+? I reckon,
not many. As a seasoned
Windows
C++
programmer
developing for desktop
applications, I've been
using the archaic GDI on
regular basis. Since the
release of
GDI+ (see (http://msdn.microsoft.com/library/default.asp?url=/library/en-us/gdicpp)
I've been using
GDI+ in new
applications and also
converting existing
applications to use GDI+.
There numerous compelling
reasons why you should be
using
GDI+, here are
some:
- Successor to GDI
- Compatible with .NET
- Optimizes many of
the capabilities of GDI
- Supports: Gradient
Brushes, Independent
Path Objects,
Transformations and the
Matrix Object, Scalable
Regions, Alpha Blending
and support for multiple
image
formats:
- BMP
-
GIF
- JPEG
- Exif
- PNG
- TIFF
- ICON
- WMF
- EMF
During my development of
Windows GUI based
applications with
GDI+, I've come
across the need to display
animated GIFs,
whilst
GDI+ does not
support displaying
animated GIFs
directly, in can be done
with a little coding.
Implementation
Firstly lets look at
drawing a simple image using
GDI+.
Collapse |
Copy Code
void CMyWnd::OnPaint()
{
CPaintDC dc(this);
Graphics graphics(&dc);
Image image(L"Test.Gif");
graphics.DrawImage(&image, 0, 0, image.GetWidth(), image.GetHeight());
}
Straight away we can see
the simplistic C++ interface
for using GDI objects. This
makes it a sure fire way for
using GDI objects. There is
no need for using
SelectObject
to select GDI objects in and
out of the device context.
For those of the readers
who are not familiar with
the format of an
animated GIF,
animated GIF is
actually a series of
GIF
frames with a delay time
associated each frame,
therefore each frame can
have a different delay time.
My implementation of
encapsulating an animated
GIF
functionality derives a
class called from
ImageEx
from
the
GDI+
Image
class. The first tucancode.net is to
determine whether or not a
GIF
is of the animated kind. The
following code demonstrates
this:
Collapse |
Copy Code
bool ImageEx::TestForAnimatedGIF()
{
UINT count = 0;
count = GetFrameDimensionsCount();
GUID* pDimensionIDs = new GUID[count];
GetFrameDimensionsList(pDimensionIDs, count);
m_nFrameCount = GetFrameCount(&pDimensionIDs[0]);
int nSize = GetPropertyItemSize(PropertyTagFrameDelay);
m_pPropertyItem = (PropertyItem*) malloc(nSize);
GetPropertyItem(PropertyTagFrameDelay, nSize, m_pPropertyItem);
delete pDimensionIDs;
return m_nFrameCount > 1;
}
m_pPropertyItem->value
is actually a
pointer to an array of
longs, each long is a delay
time which corresponds to a
GIF
frame. Because
GetPropertyItem
returns a different size
depending on what property
using interested in, a Size
is require and its the
programmer responsibility to
allocate and deallocate the
memory associated with
GetPropertyItem
.
The size is determined by
calling
GetPropertyItemSize
supplying property tag your
interested in.
Once the number of frames
and delay times have been
retrieved from the image, a
thread is created which
calls to
DrawFrameGIF
until the object destructs.
See
DrawFrameGIF
below:
Collapse |
Copy Code
bool ImageEx::DrawFrameGIF()
{
::WaitForSingleObject(m_hPause, INFINITE);
GUID pageGuid = FrameDimensionTime;
long hmWidth = GetWidth();
long hmHeight = GetHeight();
HDC hDC = GetDC(m_hWnd);
if (hDC)
{
Graphics graphics(hDC);
graphics.DrawImage(this, m_rc.left, m_rc.top, hmWidth, hmHeight);
ReleaseDC(m_hWnd, hDC);
}
SelectActiveFrame(&pageGuid, m_nFramePosition++);
if (m_nFramePosition == m_nFrameCount)
m_nFramePosition = 0;
long lPause = ((long*) m_pPropertyItem->value)[m_nFramePosition] * 10;
DWORD dwErr = WaitForSingleObject(m_hExitEvent, lPause);
return dwErr == WAIT_OBJECT_0;
}
One other interesting
aspect of this class is it
has the ability of loading a
image directly as a resource
from an executable. I
usually import my
GIF
into a project and give it a
resource type of "GIF"
and then rename the resource
ID from a numeric constant
to a string (see the example
code).
Conclusion
If you familiar with the
concepts and programming of
GDI,
GDI+ provides
some advance features and
the interface almost mirrors
the .NET GDI namespace. The
sample apps and code include
the full listings for
implementing animated GIF in
your code applications. For
code reference just search
for
GDI+ within
the code. One thing I
haven't included in this
article is starting up and
shutting the
GDI+ subsystem.
Contact UCanCode Software
To buy the source code or learn more about with: