|
Suppose there is some background image drawn on a dialog and this control is used there it appears grey,even overwriting the OnCtlColor and returning HOLLOW_BRUSH for static controls doesn't help.
Is there any way to fix it.
Great effort
|
|
|
|
|
Hi
I found this CPictureEx is such a great and useful class .
Thank you for releasing it .
I have the following question / doubt .
I'm creating Dynamic dialog boxes using InitModalIndirect in MFC with out using any resources . How can I add CPictureEx in such case ?
Currently I'm adding Standard MFC controls with CWnd::CreateEx function .
My problem is that I can not follow the given sequence to use the class i.e Create(), load() and then Draw().
Any Suggestions form any one ?
Thanks in Advance
Tim Droz
|
|
|
|
|
After creating your CWnd, call CPictureEx::SubclassWindow(HWND) function, passing CWnd::m_hWnd there. Then you can call Load() and Draw().
|
|
|
|
|
Hi Oleg
Thanks for the suggestion , actually I manage use the CPictureEx without the SubclassWindow(HWND) function (i.e just have a member variable, create , Load and then Draw()).
It was something wrong while I was trying to create the font for the dynamic Dialog.
Now I have the doubt,is it really correct ...to do that way ?
One more issue , I'm getting a Picture update problem for non animated images (like BMP) when I move the dialog I created is ther any thing that I'm missing Oleg ? Should I call the CPictureEx::Draw() on the Dialog::paint()??
Having asked you those , I should thank you again for relaseing such a greate work .
Thanks ,Tim
Tim Droz
|
|
|
|
|
It's absolutely correct to do Create instead of SubclassWindow. As for static pictures redraw problem, it's my mistake, I overlooked this situation. It can be resolved, I'll let you know by e-mail when it's done (thanks for pointing that out btw).
|
|
|
|
|
Thanks Oleg I would really appreciate it .
Hmm Licensing issue seems to be an issue ...
- Tim
Tim Droz
|
|
|
|
|
You know, Tim, I doublechecked the classes and it works fine for the still pictures. I really don't see a way for repainting problems. Can you send me an example of your project?
|
|
|
|
|
First of all, I just want to thank you for writing this class. It was exactly what I needed!
In exchange, I would like to contribute some suggestions for any future versions.
- Make it template based (the ATL version, at least)
The base class, CWindowImpl<> takes two additional parameters that are currently being left to the default values. It would be better if the CPictureExWnd class would itself be a template that takes these values as parameters.
If you name class template somelike CPictureExWndT, and then specify a typedef with the name CPictureExWnd, no one would have to change their code (unless they wanted to make use of this new utility).
Why would anyone want to do this? Well, in the ATL samples, there is a file called "atlcontrols.h" . It provides template classes to support lots of common controls. You could substitute AtlControls::CStatic instead of CWindow, and it would add the helper functions for Static controls.
Another idea would be to create a button control that animates the GIF whenever someone mouses over it. All you would need to do is specify AtlControls::CButton and in a derived class declare another DECLARE_WND_SUPERCLASS that specifies BUTTON instead of STATIC, and then add a chained message map to handle the messages. The downside would be that it would be expensive to create/destroy the thread whenever it mouses over, but that brings me to my next suggestion...
- Allow Pause/Resume of the thread
You could add a couple of member functions that will suspend/resume the thread instead of destroying/creating it everytime. Useful if you want to pause the animation frequently.
- Support jumping to a given frame
To be used in conjunction with the above, if you wanted to rewind the animation to the beginning everytime you start it up, or something along those lines.
- Inline Some Functions
If you inline some of the smaller functions, especially the ones that just return values, it helps the compiler to optimize the code if you specify the functions as inline.
---
Darrin W. Cullop
|
|
|
|
|
Great suggestions, Darrin! Some of them make me go doh. Along with true transparency support it looks like it will make a perfect v1.4 release. Thanks again!
|
|
|
|
|
Hi,
How should I use this class for creating shell extension for animated gif's within rightclick menu - similar to PicAview from acdsee.com look at:
http://www.acdsystems.com/English/Products/ImagingProducts/Utilities/Picaview/index.htm
|
|
|
|
|
You can call CPictureEx[Wnd]::Create directly and pass to it the handle of a window you wish to be a GIF's parent. Then just Load() a picture and Draw() it.
|
|
|
|
|
Initialization of the extension - GifAniShlExt::Initialize() - does not seem to be a problem. The problem is a GIF parent window as you call it - It would be a menu and I guess I would need to use MENUITEMINFO for using my preview.
Is there smth special I should be aware of?
|
|
|
|
|
First I want to thank Mr. Oleg Bykov for contributing such a useful class.
But I found one small bug inside the member function CPictureEx::ThreadAnimation(), here is the line:
const int nUnitsPerSecond = 100000; //<== Instead of 100000, it acutally should be 10000000.
// Because the Timer unit is 100-nanoseconds.
// ( 1 second = 1,000 milliseconds = 1,000,000 microseconds = 10,000,000 100-nanoseconds )
The waitable timer is only available in WinNT 4.0 & Win98 above version. To make this class also workable under Win95. We need replace the waitable timer. Here are my modifications: All the modifications are inside the compiler conditional block(#ifdef #else #endif):
(After making this modification, I realize that there is no need to put the waitable timer here. We can always use the WaitForSingleObject's timeout to safely sleep a period of time without delaying any stop request during this peroid. Am I right?)
void CPictureEx::ThreadAnimation()
{
#ifdef Win98NT
HANDLE hTimer = CreateWaitableTimer(NULL,TRUE,NULL);
if (!hTimer)
{
TRACE(_T("ThreadAnimation: couldn't create a waitable timer\n"));
return;
};
#endif
#ifdef Win98NT
// we're gonna wait for two events, whichever occurs first
// this way we won't have lags with lengthy GIF-delays
HANDLE arrHandles[2] = {hTimer, m_hExitEvent};
#endif
int nTemp = 0;
while (!m_bExitThread)
{
if (m_arrFrames[nTemp].m_pPicture)
{
///////////////////////////////////////////////////////
// Before rendering a frame we should take care of what's
// behind that frame. TFrame::m_nDisposal will be our guide:
// 0 - no disposal specified (do nothing)
// 1 - do not dispose (again, do nothing)
// 2 - restore to background color (m_clrBackground)
// 3 - restore to previous
//////// disposal method #3
HDC hMemDC = NULL;
HBITMAP hMemBM = NULL, hOldBM;
if (m_arrFrames[nTemp].m_nDisposal == 3)
{
// prepare a memory DC and store the background in it
hMemDC = CreateCompatibleDC(m_hMemDC);
hMemBM = CreateCompatibleBitmap(m_hMemDC,
m_arrFrames[nTemp].m_frameSize.cx,
m_arrFrames[nTemp].m_frameSize.cy);
if (hMemDC && hMemBM)
{
hOldBM = reinterpret_cast<hbitmap> (SelectObject(hMemDC,hMemBM));
BitBlt(hMemDC,0,0,
m_arrFrames[nTemp].m_frameSize.cx,
m_arrFrames[nTemp].m_frameSize.cy,
m_hMemDC,
m_arrFrames[nTemp].m_frameOffset.cx,
m_arrFrames[nTemp].m_frameOffset.cy,
SRCCOPY);
};
};
///////////////////////
long hmWidth;
long hmHeight;
m_arrFrames[nTemp].m_pPicture->get_Width(&hmWidth);
m_arrFrames[nTemp].m_pPicture->get_Height(&hmHeight);
if (m_arrFrames[nTemp].m_pPicture->Render(m_hMemDC,
m_arrFrames[nTemp].m_frameOffset.cx,
m_arrFrames[nTemp].m_frameOffset.cy,
m_arrFrames[nTemp].m_frameSize.cx,
m_arrFrames[nTemp].m_frameSize.cy,
0, hmHeight, hmWidth, -hmHeight, NULL) == S_OK)
{
Invalidate(FALSE);
};
if (m_bExitThread)
{
if (hMemDC)
{
// dispose local variables
SelectObject(hMemDC,hOldBM);
DeleteDC(hMemDC);
DeleteObject(hMemBM);
};
break;
};
#ifdef Win98NT
LARGE_INTEGER li;
const int nUnitsPerSecond = 10000000;
if (m_arrFrames[nTemp].m_nDelay < 5)
li.QuadPart = -static_cast<long>(10*nUnitsPerSecond);
else
li.QuadPart = -(nUnitsPerSecond*static_cast<long>(m_arrFrames[nTemp].m_nDelay));
li.QuadPart /=100;
SetWaitableTimer(hTimer,&li,0,NULL,NULL,FALSE);
// of course, we could use a casual Sleep()
// but then Stop() would take quite some time
WaitForMultipleObjects(2,arrHandles,FALSE,10000);
#else
DWORD dwTime;
if (m_arrFrames[nTemp].m_nDelay < 5)
dwTime = 10*10;
else
dwTime = m_arrFrames[nTemp].m_nDelay*10;
WaitForSingleObject(m_hExitEvent,dwTime);
#endif
if (m_bExitThread)
{
if (hMemDC)
{
// dispose local variables
SelectObject(hMemDC,hOldBM);
DeleteDC(hMemDC);
DeleteObject(hMemBM);
};
break;
};
// disposal method #2
if (m_arrFrames[nTemp].m_nDisposal == 2)
{
HBRUSH hBrush = CreateSolidBrush(m_clrBackground);
if (hBrush)
{
RECT rect = {
m_arrFrames[nTemp].m_frameOffset.cx,
m_arrFrames[nTemp].m_frameOffset.cy,
m_arrFrames[nTemp].m_frameOffset.cx + m_arrFrames[nTemp].m_frameSize.cx,
m_arrFrames[nTemp].m_frameOffset.cy + m_arrFrames[nTemp].m_frameSize.cy };
FillRect(m_hMemDC,&rect,hBrush);
DeleteObject(hBrush);
};
}
else
if (hMemDC && (m_arrFrames[nTemp].m_nDisposal == 3) )
{
// put it back
BitBlt(m_hMemDC,
m_arrFrames[nTemp].m_frameOffset.cx,
m_arrFrames[nTemp].m_frameOffset.cy,
m_arrFrames[nTemp].m_frameSize.cx,
m_arrFrames[nTemp].m_frameSize.cy,
hMemDC,0,0, SRCCOPY);
// dispose local variables
SelectObject(hMemDC,hOldBM);
DeleteDC(hMemDC);
DeleteObject(hMemBM);
};
};
nTemp++;
if (nTemp == m_arrFrames.size())
{
nTemp = 0;
// init the screen for the first frame,
RECT rect = {0,0,m_PictureSize.cx,m_PictureSize.cy};
FillRect(m_hMemDC,&rect,(HBRUSH)(COLOR_WINDOW));
};
};
#ifdef Win98NT
CloseHandle(hTimer);
#endif
}
Wayne King
10 Oct 2001
|
|
|
|
|
Thank you for your kind words. You're absolutely right in both of your statements. First, I didn't pay attention to the fact that waitable timers are only available on Win98. Second, I didn't realize that I could use dwTimeOut parameter of WaitForSinlgeObject. Ironically enough, we had to solve the similar problem with our current project and one of my co-workers showed me this solution. Unfortunately, the article was already submitted.
I'll definitely redo the class to make it more compatible. Thanks again, I'll surely mention you in the new article.
|
|
|
|
|
As far as I know, including support for GIF files in your application requieres paying royalties to the guys who patented the GIF format.
If I use this class in my app, even if it is totally free, I still have to pay the royalties, or am I wrong (I hope)???
-- LuisR
--------
Luis Alonso Ramos
Chihuahua, Mexico
www.luisalonsoramos.com
|
|
|
|
|
I've made a research on the subject and found that there's no definite answer. Unisys holds the rights to the LZW algorythm used in GIF so you cannot implement your own decoder or use someone else's without paying to Unisys (that includes Microsoft development tools like Visual Basic). But in the case of CPictureEx, there's no custom LZW-decoder - it uses the WinAPI function! (OleLoadPicture) So the question is whether we can use WinAPI functions and not pay to anyone (Microsoft has an agreement with Unisys btw - see Q193543). I don't know the answer and I doubt anyone does (save Unisys or Microsoft lawyers).
|
|
|
|
|
from http://www.unisys.com/unisys/lzw/ :
"Microsoft Corporation obtained a license under the above Unisys LZW patents in September, 1996. Microsoft's license does NOT extend to software developers or third parties who use Microsoft
toolkit, language, development or operating system products to provide GIF read/write and/or any other LZW capabilities in their own products (e.g., by way of DLLs and APIs). The complete statement by Microsoft can be found at Microsoft's
developer-oriented Web site at http://www.microsoft.com/DEVONLY/Unisys.htm. Software developers and third parties who wish to include Microsoft toolkit, language, development or operating system products in their own products for providing GIF or any other LZW capability should contact Unisys for a license as instructed below. Other forms of LZW are, for example, TIFF-LZW, PDF and Postscript-2.
"
i have talked to Unisys about this (how come MS gets to distribute LZW code, but i can't?). the answer is simple - MS paid a lot of money to be able to do so.
-c
------------------------------
Smaller Animals Software, Inc.
http://www.smalleranimals.com
|
|
|
|
|
you are correct.
http://www.unisys.com/unisys/lzw/
-c
------------------------------
Smaller Animals Software, Inc.
http://www.smalleranimals.com
|
|
|
|
|
Chris ,
Do you know if this has been tested in court ?
Regardz
Colin J Davies
|
|
|
|
|
What has been tested in court?
They hold the patents and for the most part can do anything they damn well please.
If an application is using LZW without permission, then at any point Unisys can come down on them. Under US law, they are not required to take action against all improper use of the patent.
Tim Smith
Descartes Systems Sciences, Inc.
|
|
|
|
|
>> What has been tested in court?
>> They hold the patents and for the most part can do anything they damn well please. <<
It's not that simple. First of all, just because a patent has ben granted, doesn't mean it can't be challenged. To be patented, an invention must be original and "not obvious" to someone trained inthe field. UniSys's patent in fact only covers the improvements made by Mr. Welsh on the algorithm previously invented by Mr Lev & Mr Zimpl (not certain about those name)
Now, there are many ways one could compress a file, but only compressed, there's only one way to restore it to it's original contents. Hence, it could be argued (And I think successfully), that a LZW *compressor* is patentable, but a *decompressor* is not.
However, challenging the patent would entail a very expensive lawsuit, which would require instructing a jury a obscure techinical matter, and hoping they would understand. So far, everyone decided that it would be cheaper to pay them off.
Truth,
James
|
|
|
|
|
as Tim noted, since they have the patent (in the US and some other countries), it's pretty much beyond question.
i haven't heard of anyone actually going to court. but i'm fairly sure i would've heard about it on Slashdot or on the graphics newsgroups, if it did happen. i do know they've sent lawyers after some developers; for example, there is a set of freeware image tools for *nix called "GD". the authors got into some hot water a couple of years ago for distributing GIF/LZW code - primarily because the tools are intended for server-side processing and Unisys is really uptight about unlicensed LZW on servers; they actually have (had?) a program where server owners could pay Unisys a yearly fee, to exempt them from any possible penalties in case they're caught using GIF software that doesn't have a Unisys license. GD ended up dropping GIF for PNG.
luckily their patent runs out in June 2003.
-c
------------------------------
Smaller Animals Software, Inc.
http://www.smalleranimals.com
|
|
|
|
|
>> luckily their patent runs out in June 2003.
Free-Quoted (I think it was on UNISYS website, but I'm not sure)
"the basic patent on LZW will run out in... Patents on some variants will run longer". With GIF being a variant, we'll see.....
|
|
|
|
|
"With GIF being a variant, we'll see....."
UniSys does NOT own the patent on the GIF format, only the LZW algorithm. THe GIF format was designed by CompuServe, which, as far as I know, have not attempted to enforce patent protection on it.
Truth,
James
|
|
|
|
|
The statement I remember was "original LZW patent expires in foo, whereas patents on various variants run much longer", and Now GIF uses an LZW variant.
|
|
|
|
|