Click here to Skip to main content
Email Password   helpLost your password?

Sample Image

Introduction

Class CPictureEx was written for an MFC-project t

hat required support for banners in JPEG and GIF formats. Static banners weren't hard to display using the OleLoadPicture function and the IPicture interface, but dealing with animated GIFs was a whole different story.

Having rummaged through numerous Internet-links, I discovered that there's only one free option available - a COM-object by George Tersaakov on CodeGuru. Unfortunately, it had problems with displaying some of my test GIFs. Of course, I could buy a third-party library, but in that case, I would pay for an extra functionality (which I didn't actually need). I decided to give it a try and write my own class. The basic idea was to split a GIF into separate frames and display the frames with the familiar combination of OleLoadPicture and IPicture. After thoroughly reading through specifications of GIF87a and GIF89a, I wrote the class that I bring to your attention. Note that CPictureEx can display not only GIFs (including animated GIFs) but also JPEG, BMP, WMF, ICO and CUR (that is, everything that OleLoadPicture knows of). Later on, I wrote an ATL-version of the class.

How you use the MFC-version (CPictureEx)

Add a static text or a Picture control to your dialog (group box will do the trick as well); change the ID of that control to something like IDC_MYPICTURE; use the ClassWizard to associate a member variable (for example, m_Picture) with the control added, Category - Control, Variable type - CStatic; in your dialog's header file, replace the variable type from CStatic to CPictureEx (don't forget to #include "PictureEx.h" and add PictureEx.h and PictureEx.cpp to your project); in OnInitDialog (or anywhere you fancy), add these lines:

if (m_Picture.Load(_T("mypicture.gif")))
    m_Picture.Draw();

Sit back and enjoy the animation :)

You can also treat CPicture as a standard CStatic, and manually create it (you'll have to, if your host window is not a dialog) by calling CPictureEx::Create(), and then CPictureEx::Load and CPictureEx::Draw.

How you use the ATL-version (CPictureExWnd)

To use the ATL-version (CPictureExWnd), follow the same steps, but instead of using ClassWizard, manually add a variable of type CPictureExWnd in your class and add the following code to your WM_INITDIALOG handler function:

HWND hWnd = GetDlgItem(IDC_MYPIC);
if (hWnd) m_wndBanner.SubclassWindow(hWnd);

After that, you can call CPictureExWnd::Load() and CPictureExWnd::Draw(). Of course, you can also call CPictureExWnd::Create directly - CPictureExWnd is just another window with some extra functionality in its window procedure.

Interface functions

CPictureEx[Wnd]::Load is available in three versions:

BOOL Load(LPCTSTR szFileName);

This version loads a picture from the file szFileName. The function's return type indicates the success of the loading.

BOOL Load(HGLOBAL hGlobal, DWORD dwSize);

This Load gets a handle to the global memory block, allocated with GlobalAlloc and GMEM_MOVEABLE flag. The function does not free the memory, so don't forget to GlobalFree it. The return value indicates the success of the loading.

BOOL Load(LPCTSTR szResourceName,LPCTSTR szResourceType);

The function gets a name for the resource with a picture and a name for the type of that resource. For example:

m_Picture.Load(MAKEINTRESOURCE(IDR_MYPIC),_T("GIFTYPE"));

After loading a picture, display it with CPictureEx[Wnd]::Draw() function. If the picture is an animated GIF, the function will spawn a background thread to perform the animation; if it's a still picture, it will be displayed right away with OleLoadPicture/IPicture. You can stop the spawned thread anytime with the CPictureEx[Wnd]::Stop() function. If you want to not only stop the animation but to free all its resources, use CPictureEx[Wnd]::UnLoad() (CPictureEx[Wnd]::Load() calls UnLoad() automatically).

By default, the picture's background is filled with COLOR_3DFACE (the background color of dialog windows). If you need to change the picture's background, call CPictureEx[Wnd]::SetBkColor(COLORREF) after calling CPictureEx[Wnd]::Load().

Version history

You must Sign In to use this message board.
 
 
Per page   
 FirstPrevNext
GeneralCImageList and CPictureEx
Hoitabuam
7:50 25 Jan '10  
CPictureEx works great but I have a CImageList (m_ilist) thats filled with Icons:
m_ilist.Add(AfxGetApp()->;LoadIcon(IDI_RSGruen));
I tried various variants with CPictureEx (replace the Icons with animated Gif's) but without any success as CImageList only accepts Icons or Bitmaps.
Thx in advance for any suggestions!
Generalsuggestion SetCursor
guyuewuhua
20:55 9 Sep '09  
//CPictureEx.h
void SetLink(const CString strLink);
afx_msg void OnLButtonDown(UINT nFlags, CPoint point);
afx_msg BOOL OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message);
HCURSOR m_Cursor;
BOOL m_bLinkFlag;
CString m_LinkText;


//CPictureEx.cpp
//ADD MESSAGE_MAP
ON_WM_SETCURSOR()
ON_WM_LBUTTONDOWN()

//
CPictureEx::CPictureEx()
{
......
m_bLinkFlag = FALSE;
m_LinkText = "";
m_Cursor = AfxGetApp()->LoadStandardCursor(IDC_HAND);
}

BOOL CPictureEx::OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message)
{
if (m_bLinkFlag&&m_LinkText!="")
{
::SetCursor(m_Cursor);
return TRUE;
}
return CStatic::OnSetCursor(pWnd, nHitTest, message);
}

void CPictureEx::OnLButtonDown(UINT nFlags, CPoint point)
{

if (m_bLinkFlag&&m_LinkText!="")
{
ShellExecute(NULL,_T("open"),m_LinkText.IsEmpty() ? m_LinkText : m_LinkText,NULL,NULL,SW_SHOWNORMAL);
}
CStatic::OnLButtonDown(nFlags, point);
}


void CPictureEx::SetLink(const CString strLink)
{
if(strLink != "")
{
m_bLinkFlag = TRUE;
ModifyStyle(0,SS_NOTIFY);
m_LinkText = strLink;
}
}
GeneralThanks
TClarke
1:58 4 Aug '09  
Nicely done Smile

Cheers
Tom

Philosophy: The art of never getting beyond the concept of life. Religion: Morality taking credit for the work of luck.

GeneralImporting gif resources in VS2005 - Invalid File
Elliot Rice
6:52 3 Apr '09  
Great code! Thanks!

I did have some trouble importing my animated gifs as resources to my VisualStudio 2005 project but I solved the problem.

When I went to "Add Resource" -> "Import" and tried to select the gif as the file to import the IDE moaned about the file being invalid. However, changing the file extension to ".bin" and then doing the import worked fine allowing me to load a gif from a compiled resource.

if (m_BusyGif.Load(MAKEINTRESOURCE(IDR_BUSY_GIF),_T("GIF")))
m_BusyGif.Draw();

Also see the Ajax thread for great loading gifs!
GeneralThank you! It's a great class!
yiwenjun
11:33 29 Mar '09  
Thank you! It's a great class!
GeneralThanks for this great class!!!
czy0408
15:59 5 Mar '09  
Thanks for this great class!!! Big Grin
GeneralLicense ?
kosasihkho
20:17 22 Feb '09  
Hai,

This is a great class...
Does this code have a license ? Is it ok if we attempt to add your source code to our software ?

This is my email address:
kosasihkho@gmail.com

Please contact me ASAP

Thanks
GeneralThanks for this great class!!!
coder_kevin
2:52 12 Feb '09  
Oleg - you are very kind and appreciated. This class is well written and solves problems that many of us have. Thanks again... Smile
GeneralHow to display a bitmap resource using PictureEx
Shup
14:15 12 Jun '08  
First, great job and thanks for sharing!

I currently have the need to display both GIF type and BMP type resources on the same static controls when needed. Your control is excellent for this purpose, but I am having trouble in these lines of code:

if(m_stTitle.Load(MAKEINTRESOURCE(IDB_TITLE_00), _T("BMP")))
{
m_stTitle.Draw();
}

The above lines of code doesn't seem to work, my guess is that I should replace _T("BMP") with something.

Thanks in advance!

Shup

Shupantha
Mind & Machines LTD

GeneralRe: How to display a bitmap resource using PictureEx
Dave Streeter
8:01 12 Mar '09  
Supposedly it is RT_BITMAP not "BMP" but it still fails later in the OleLoadPicture() call. Have you have any luck?
GeneralRe: How to display a bitmap resource using PictureEx
Shup
8:24 12 Mar '09  
Nah, haven't had any luck with that yet!

Thanks for replying Smile

Regards,

Shup
Mind & Machines

GeneralUseful source of progress animators gifs
Pandele Florin
0:59 24 Jan '08  
http://www.ajaxload.info/[^]
MAKE SURE YOU CHECK "Transparent background" for ideal results. Smile
QuestionAnimation Gif as Splash before start..
shizu looi
17:28 11 Sep '07  
Hi..
I would like to know that how to make an animation .gif as splash before start application..??
If is bitmap, then i can make it as splash with call .LoadBitmap..
but if is animation .gif, then i don't know how to do..

can anyone help me up..??

thank you..

shizu
GeneralTransparent background
Shlomo
8:09 21 Jun '07  
Can I make the gif background transparent?Smile
QuestionHello
SuF1234
2:07 8 Mar '07  
Cry
I'm writing in Visual C++ a project in Win32. In my project there are arrays and on the arrays I want to use GIF animation. Please help me and tell me how to do it...

Thank you in advance,
Sufa


GeneralNice class, But LNK2001 occurs when use static lib
Jerry.Wang
1:06 30 Jan '07  
Hi,

That is a nice class indeed.

But when I use the class in a static lib, compiled by VS2005.

It will success when I choose "Debug"
It will failed when I choose "Release"

Error 4 error LNK2001: unresolved external symbol "public: __thiscall std::exception::exception(char const * const &)" (??0exception@std@@QAE@ABQBD@Z) libcpmt.lib


Error 6 error LNK2001: unresolved external symbol "public: virtual char const * __thiscall std::exception::what(void)const " (?what@exception@std@@UBEPBDXZ) libcpmt.lib


Error 8 error LNK2001: unresolved external symbol "public: virtual __thiscall std::exception::~exception(void)" (??1exception@std@@UAE@XZ) libcpmt.lib

Error 10 error LNK2001: unresolved external symbol "public: __thiscall std::exception::exception(class std::exception const &)" (??0exception@std@@QAE@ABV01@@Z) libcpmt.lib


Error 12 error LNK2001: unresolved external symbol "public: __thiscall std::exception::exception(void)" (??0exception@std@@QAE@XZ) libcpmt.lib


GeneralGIF doesn't animate with ShowWindow()
btboja
23:40 31 Jul '06  
Hi,

I've got a dialog which has CPictureEx on it to show a GIF animation.
It works just fine when I invoke DoModal() on my dialog.
However, it doesn't animate GIF when i show my dialog with ShowWindow(SW_SHOW) Confused .
Can it be animated with ShowWindow()?

Thanks,

Bojan
GeneralLoad More GIF one time
badboyyp
21:53 25 Jul '06  
First please accept my thanks for you work
can you load more than one GIF one time?how to change the code to resolve it ?
another problem is that if i want to call Draw in a non-window enviroment ,how can I to do ?
do you have a version which the base class is CObject,in my opinion ,if the base class is CObject ,then it can be used more freely,could you please tell how to change the code?

虽非法

GeneralOptimized GIF problem (global palette)
daganesh
0:32 16 Jul '06  
Hi there,
I am enjoying this class for some time now, displaying static and animated images, and recently run into the following problem:
Some of the animated GIF files, are uncorrectly displayed.
What you see in each new frame is only the "modified" part of the GIF and not the entire GIF.
It happens, as far as I know, for optimized GIFs using a single (global) palette, and not a different palette for each frame.
The GIFs are created using gdImage dll, where each new frame, uses the previous frame as reference.

did anyone encounter similaar problems displaying optimized GIFs?

TIA,
Dagan
GeneralModified Load() for DLL Resource
HydroDan
9:03 27 Jun '06  

The dialog and GIF resource in my application is embedded in a DLL, and the original ltPictureEx::Load( szResourceName, szResourceType ) couldn't locate the resource. Here is a modified version that correctly loads the resource from the DLL at runtime. (for attaching the GIF resource, I followed the instructions here : CompleteActiveX) The actual change was using AfxFindResourceHandle() instead of AfxGetResourceHandle().


BOOL ltPictureEx::Load(LPCTSTR szResourceName, LPCTSTR szResourceType)
{
ASSERT(szResourceName);
ASSERT(szResourceType);
// this call will find resources in a DLL, AfxGetResourceHandle() doesn't
HINSTANCE hlocation = AfxFindResourceHandle(szResourceName,szResourceType);

HRSRC hPicture = FindResource(hlocation,szResourceName,szResourceType);
HGLOBAL hResData;
if (!hPicture || !(hResData = LoadResource(hlocation,hPicture)))
{
TRACE(_T("Load (resource): Error loading resource %s\n"),szResourceName);
return FALSE;
};
DWORD dwSize = SizeofResource(hlocation,hPicture);

// hResData is not the real HGLOBAL (we can't lock it)
// let's make it real
HGLOBAL hGlobal = GlobalAlloc(GMEM_MOVEABLE | GMEM_NODISCARD,dwSize);
if (!hGlobal)
{
TRACE(_T("Load (resource): Error allocating memory\n"));
FreeResource(hResData);
return FALSE;
};

char *pDest = reinterpret_cast (GlobalLock(hGlobal));
char *pSrc = reinterpret_cast (LockResource(hResData));
if (!pSrc || !pDest)
{
TRACE(_T("Load (resource): Error locking memory\n"));
GlobalFree(hGlobal);
FreeResource(hResData);
return FALSE;
};
CopyMemory(pDest,pSrc,dwSize);
FreeResource(hResData);
GlobalUnlock(hGlobal);

BOOL bRetValue = Load(hGlobal,dwSize);
GlobalFree(hGlobal);
return bRetValue;
}

AnswerRe: Modified Load() for DLL Resource
chris175
10:44 27 Jun '06  
DLL's are tricky...

Instead of using AfxFindResourceHandle use the following...

HINSTANCE GetDLLInstance								()
{
HINSTANCE hInst = GetModuleHandle("MYDLLNAME.dll");
if (hInst == NULL)
{
// Check for the debug dll name.
hInst = GetModuleHandle("MYDLLNAMEd.dll");
ASSERT(hInst != NULL);
}
return hInst;
}


Chris
GeneralRe: Modified Load() for DLL Resource
Dave Streeter
0:12 13 Mar '09  
That does not work for a Bimap in the resources! Do you know how to get OleLoadPicture() working for bitmap resources?

Thanks

Dave
Generalhelp,an error occured
lsmart
20:10 16 May '06  
in CEditView single document
I do like this
xxxxDoc.h
CPictureEx m_Gif;
xxxxDoc.cpp
CXXXXDoc::test()
{
m_Gif.Create("",NULL,CRect(30,30,100,100),(CEditView *)m_viewList.GetHead(),NULL);
m_Gif.ShowWindow(SW_SHOW);
if(m_Gif.Load("d:\\test.gif"))
m_Gif.Draw();
}
no error or warings
but no gif displayed.

thanks

lsmart
GeneralFit Size error
lemonxinmei330
17:38 7 May '06  
You said if I want to display the gif according to the size of the window, I should changle two places as following:

m_PictureSize.cx = m_pGIFLSDescriptor->m_wWidth;
m_PictureSize.cy = m_pGIFLSDescriptor->m_wHeight;

pBlockSize->cx = pImage->m_wWidth;
pBlockSize->cy = pImage->m_wHeight;

but if I do that I found that the first frame of gif is display right, but the other frames display wrong, why? And Is there any place I should change?
GeneralRe: Fit Size error
guyuewuhua
22:34 24 Aug '09  
the same question


Last Updated 24 Nov 2001 | Advertise | Privacy | Terms of Use | Copyright © CodeProject, 1999-2010