|

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
BOOL Load(...) - loads a GIF and prepares an object for drawing;
BOOL Draw() - draws the picture or continues animation;
void Stop() - stops animation;
void UnLoad() - stops animation and releases all resources;
void SetBkColor(COLORREF) - sets the fill color for transparent areas;
COLORREF GetBkColor() - gets the current fill color;
BOOL IsGIF() - TRUE if the current picture is a GIF;
BOOL IsAnimatedGIF() - TRUE if the current picture is an animated GIF;
BOOL IsPlaying() - TRUE if an animation is being shown for the current picture;
SIZE GetSize() - returns the picture's dimensions;
int GetFrameCount() - returns the number of frames in the current picture;
BOOL GetPaintRect(RECT *lpRect) - returns the current painting rectangle;
BOOL SetPaintRect(const RECT *lpRect) - sets the current painting rectangle;
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
- 1.0 (7 Aug 2001) - initial release;
- 1.1 (6 Sept 2001) - ATL version of the class;
- 1.2 (31 Oct 2001) - various bugfixes:
- Fixed a problem with loading GIFs from resources in MFC-version of the class for multi-module apps. Thanks to Ruben Avila-Carretero for finding this out.
- Got rid of waitable timer in
ThreadAnimation(), now CPictureEx[Wnd] works in Win95 too. Thanks to Alex Egiazarov and Wayne King for the idea.
- Fixed a visual glitch when using
SetBkColor. Thanks to Kwangjin Lee for finding this out.
- 1.3 (18 Nov 2001) - a bugfix and new features:
- Fixed a DC leak. One DC leaked per each
UnLoad() (forgot to put a ReleaseDC() in the end of CPictureExWnd::PrepareDC() function).
- Now it is possible to set a clipping rectangle using
CPictureEx[Wnd]::SetPaintRect(const LPRECT) function. The LPRECT parameter tells the class what portion of a picture it should display. If the clipping rect is not set, the whole picture is shown. Thanks to Fabrice Rodriguez for the idea.
- Added support for
Stop/Draw. Now you can Stop() an animated GIF, then Draw() it again, it will continue animation from the frame it was stopped on. You can also know if a GIF is currently playing, with the help of IsPlaying() function.
- Got rid of math.h and made
m_bExitThread volatile. Thanks to Piotr Sawicki for the suggestion.
| You must Sign In to use this message board. |
|
| | Msgs 1 to 25 of 144 (Total in Forum: 144) (Refresh) | FirstPrevNext |
|
 |
|
|
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
|
| Sign In·View Thread·PermaLink | 5.00/5 (1 vote) |
|
|
|
 |
|
|
 |
|
|
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
|
| Sign In·View Thread·PermaLink | 1.50/5 (2 votes) |
|
|
|
 |
|
|
 |
|
|
 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
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
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
|
| Sign In·View Thread·PermaLink | 2.00/5 (2 votes) |
|
|
|
 |
|
|
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) . Can it be animated with ShowWindow()?
Thanks,
Bojan
|
| Sign In·View Thread·PermaLink | 1.67/5 (2 votes) |
|
|
|
 |
|
|
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?
虽非法
|
| Sign In·View Thread·PermaLink | 2.00/5 (1 vote) |
|
|
|
 |
|
|
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
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
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; }
|
| Sign In·View Thread·PermaLink | 1.00/5 (1 vote) |
|
|
|
 |
|
|
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
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
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
|
| Sign In·View Thread·PermaLink | 2.00/5 (1 vote) |
|
|
|
 |
|
|
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?
|
| Sign In·View Thread·PermaLink | 1.56/5 (3 votes) |
|
|
|
 |
|
|
Your example is display the gif-animation in a dialog, but I want to display it in a MFC view, and I use the following code:
m_picture.Create(NULL, SS_CENTER, rect, this, 100); if (m_picture.Load(MAKEINTRESOURCE(IDR_GIF1),_T("GIF"))) m_picture.Draw();
but I found it didn't work, there is no gif display.why?
|
| Sign In·View Thread·PermaLink | 2.00/5 (2 votes) |
|
|
|
 |
|
|
Hi great class,
In your comments you say that "If your parent window is not a dialog..." just call the CPictureExWnd::Create(). Stupid newbie question but what parameters should I pass to it?
Thanks  Chris
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
if you call it in a windows or childwindow, you can pass the last para(the front three you can specify freely) this(the pointer) is ok,but when it is called in a non window enviroment, I till now haven't find a best way 
虽非法
|
| Sign In·View Thread·PermaLink | 2.00/5 (1 vote) |
|
|
|
 |
|
|
I want to retrieve each frame from a GIF file and store them in CBitmaps. How can i do that? I`ve read your code but it`s a bit too complex for me and i heaven`t fully understood it ...Thanks in advance
|
| Sign In·View Thread·PermaLink | 3.25/5 (5 votes) |
|
|
|
 |
|
|
Hi there!
I was tring to use this control in a "please wait" dialog. The dialog is modeless, so I can show it, do some processing and then destroy it. The problem, is that if I use some very slow API or function call that does not processes the windows message pool, it seems to hang, even if the animation thread is running. I don't know why, but the control never gets to be updated/painted, so the animation stops.
Do you have any suggestion on how to solve this problem? Thanks for you time.
ALMC
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
I wanted to just play the .gif once, so I #if'ed out the old code and added a couple of lines to the end of ThreadAnimation():
m_nCurrFrame++; if (m_nCurrFrame == m_arrFrames.size()) #if 0 m_nCurrFrame = 0; // init the screen for the first frame, HBRUSH hBrush = CreateSolidBrush(m_clrBackground); if (hBrush) { RECT rect = {0,0,m_PictureSize.cx,m_PictureSize.cy}; FillRect(m_hMemDC,&rect,hBrush); DeleteObject(hBrush); }; // done restarting #else m_nCurrFrame--; // reset to last frame Stop(); #endif
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
Have tried multiple things to embed animated gif into resource - import resource, get message back: " is not a valid GIF file" and does not add. Could someone give me some additional instruction on this? Thanks
Dave Galligher Director of Product Development Cougar Mountain Software davegalligher@cougarmtn.com Voice: 208.375.4455 x180 Fax: 208.375.4460
|
| Sign In·View Thread·PermaLink | 5.00/5 (1 vote) |
|
|
|
 |
|
|
In resource view clicked resource ,then Insert ,choose custom, you can name your resource type, then you can import the gif resources to your custom resource.
|
| Sign In·View Thread·PermaLink | 5.00/5 (1 vote) |
|
|
|
 |
|
|
This took me a while to figure out. Whatever you name the resource "Type" in the resources, needs to be the "Type" you send in the Load() call. When adding an animated GIF as type GIF, VS doesn't let you. You can get around this by changing the file name to something else. The author of CompleteActiveX does a good job of explaining this.
|
| Sign In·View Thread·PermaLink | 1.75/5 (4 votes) |
|
|
|
 |
|
|
I’m working in an activex control, and I want to display a gif file on its surface, so i added your class to my project and did the following. I added a property named GIFPicture of type CString to hold the path of the gif file, and in the OnGIFPictureChange handler I added code to embed the gif file in the memory as the following(as u did in Load(CString) function):
CFile GIFPictureFile(m_cstrGIFPicture, CFile::modeRead | CFile::typeBinary); DWORD dFileSize = GIFPictureFile.GetLength(); HGLOBAL hgGIFPicture = GlobalAlloc(GMEM_MOVEABLE | GMEM_NODISCARD, m_dwFileSize + sizeof(ULONG));
the problem occur when i want to display a GIF file with one frame, in this function:
OleLoadPicture(pStream, dFileSize, FALSE, IID_IPicture, (LPVOID *)& pPicture);
it doesn’t return a valid value, and the pPicture stay empty.
i want to ask why this happened, and how to fix it ?
Thanks for help
ken san
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
I was trying to use this in my WinCE Dialog based application, but it is giving error not found
Can u suggest a solution.
Thanks
|
| Sign In·View Thread·PermaLink | 1.67/5 (6 votes) |
|
|
|
 |
|
|
Thank you for your code,But there is a small problem that I meet is,after load the GIF file,I've found it is to big on the window's dialog,Is there any way to fix it to fit proper size ?? thank you.
KW-Rix
|
| Sign In·View Thread·PermaLink | 2.71/5 (6 votes) |
|
|
|
 |
|
|
General News Question Answer Joke Rant Admin
|