C++ Q&A: Do You Have a License for that GIF? Pr...

We were unable to locate this content in de-de.

Here is the same content in en-us.

From the March 2002 issue of MSDN Magazine
MSDN Magazine
Do You Have a License for that GIF? PreSubclassWindow, EOF in MFC, and More
Paul DiLascia
Download the code for this article: C0203.exe (383KB)
A fter my October 2001 column in which I showed how to use IPicture to display GIF and JPEG images, a number of readers sent e-mail asking whether they had to pay royalties to display GIF images. As many of you are aware (and as many of you are no doubt unaware), the Lempel Ziv Welch (LZW) algorithm used in the GIF format is patented by Unisys Corporation. If your program reads or writes GIF images, the law may require you to license the patent from Unisys.
      To get the full scoop, I went to http://www.unisys.com/unisys/lzw. Unfortunately, I could not decipher, even after several readings, the circumstances under which a developer would be required to pay a fee. If you're writing a GIF-to-BMP converter, do you have to pay? (Most likely.) What if all you do is display a GIF image in your About dialog? The issue is complicated by the fact that you may be using a commercial product that's already licensed the algorithm. To get clarification, I sent e-mail to the folks at Unisys. A few days later I received a Word document, a boilerplate questionnaire asking me about my application. When I reminded them I was wearing my writer's cap, not writing an application, I got a polite answer that amounted to: it's very complicated, and would I like to talk to their lawyers?
      What about Microsoft? Do the friendly Redmondtonians have anything to say about this? Knowledge Base article Q193543 says:
Microsoft has obtained a license from Unisys to use the .gif file format and other LZW technologies covered by the Unisys-owned U.S. and foreign patents in a number of Microsoft products.
      However, this license does not extend to third-party developers using Microsoft development products to develop applications. Third-party developers must have a license from Unisys in the form of a written agreement. For more information...
      So the upshot is that, unfortunately, I can't give you any help. If you're writing a program that reads or writes GIFs, you should go to the Unisys site and try to decipher it yourself. The folks at Unisys will be happy to give you their lawyers' phone number. Needless to say, the whole GIF/LZW patent thing has created quite a controversy, one that stirs the hearts of free software libertarians around the planet. You can check out http://lzw.info for a quick overview or search the Web for "LZW patent".

Q I have a subclass of CListBox. In order for it to provide its specialized behavior, the listbox must be owner-drawn. I overrode the virtual function PreCreateWindow to force the LBS_OWNERDRAWFIXED style to be set. This works fine if I create the listbox myself. If the listbox is part of a dialog loaded from a resource, PreCreateWindow is never called. How do I ensure the LBS_OWNERDRAWFIXED style is set in this case?
Frank Lagattuta

A The short answer is: use PreSubclassWindow.
      The long answer follows. PreCreateWindow is a special CWnd virtual function that MFC calls, as you might guess, just before creating a window. When you call CWnd::Create or CWnd::CreateEx to create a window, MFC calls CWnd::PreCreateWindow before invoking Windows® to actually create your window for you.
BOOL CWnd::CreateEx(...)
{
  CREATESTRUCT cs;
  •••
  // init cs

  if (!PreCreateWindow(cs)) {
    PostNcDestroy();
    return FALSE;
  }
  •••
  // create the window

  return TRUE;
}
      But dialogs aren't created in this fashion. Dialogs are created when you call CDialog::DoModal, in which case MFC loads your dialog template using ::CreateDlgIndirect, which is roughly equivalent to ::DialogBox. Either way, Windows creates the controls internally—CWnd::CreateEx is never invoked. So your control's PreCreateWindow never gets called.
      But when you connect your control to a CWnd-derived object instance, such as your specialized listbox, you have to call SubclassDlgItem, which calls SubclassWindow, and here MFC calls another specialized virtual function, PreSubclassWindow. This is your big chance in life to do things like change the style.
void CMyListBox::PreSubclassWindow()
{
  // turn on owner-draw
  ModifyStyle(0,LBS_OWNERDRAWFIXED);
}
      In fact, PreSubclassWindow is the preferred place to do stuff like this because MFC also calls PreSubclassWindow when you create a window with CreateEx. In other words, PreSubclassWindow covers both cases—dialog or standalone creation—so if you set the style in PreSubclassWindow, you don't need to do it in PreCreateWindow, too.

Q I'm using the CFile class in my app and I know how to open, write, and close the file using this class, but I don't know (as is most important) how to read the file at its end (EOF). I'm handling CFileException::endOfFile, but I get an infinite loop.
Alessandro Chiodo

A It does seem odd, doesn't it? I mean, when you read to the end of the file, you'd expect to get an end-of-file exception, right? What else would an endOfFile exception be good for? But as it turns out, MFC doesn't use CFileException::endOfFile in this case. To check for end-of-file, you have to test whether the number of bytes actually read is less than the number of bytes you requested.
CFile file;
file.Open();
char mybuf[BUFSIZ];
UINT nread;
do (nread=file.read(buf, BUFSIZ)) {
  •••
// process nread bytes

} while (nread==BUFSIZ);
It may seem strange to do it this way, but hey—I don't make the rules; I just report 'em.

Q I want to debug a program I wrote in C++ that triggers from another application. Consider the following:
AppA -> calls plugin B -> calls my.dll
I have no source code available for AppA or the plugin—only my.dll. I want to debug my.dll when called from AppA. How do I do this?
Chamika Gunathilaka

A It's easy. In Visual Studio®, just go to Project | Settings and select the Debug tab. Normally, Visual Studio fills "executable for debug session" with the name of your executable, but you can enter any program you want. For example, you could use c:\SomeDir\AppA.exe. You can even specify a different working directory and arguments to pass to your program. Figure 1 shows the details. This technique is commonly used to debug DLLs, namespace extensions, COM objects, and other plug-ins invoked from some EXE other than your own.

Figure 1 Debugging One App through Another
Figure 1 Debugging One App through Another

Q I recently read your column describing a class called CPicture. It was most helpful, and is exceptionally easy to use. I am wondering if two problems that I am trying to solve could be handled as easily. I want to display JPGs, but in some cases I want to be able to rotate the display 90 degrees. Also, I'd like to be able to generate small bitmaps that could be used as thumbnail images in a list.
Dan Byron

A Well, I'm glad my class was so helpful. Now I suppose after flattering me, you expect me to answer your question, eh? Tell me, why do you want to rotate the image? Can't you tell the user to rotate his head? Do they expect you to do everything?
      OK, OK. You don't want your customers breaking their necks and filing a class action suit, so let's try to figure this thing out. One way to rotate is to map the pixels yourself. That is, represent the rotation as a matrix transformation in x,y space
  cos A -sin A

  sin A  cos A
which, if you remember from high school trigonometry (the advanced course) or college linear algebra, means that if you have a point (x,y), the rotated point is (x*cos(A) + y*sin(A), -x*sin(A) + y*cos(A)), where A is the angle in radians (2p radians = 360 degrees). So you just load your bitmap, select it into a device context and call GetPixel and SetPixel to map all the pixels as described, and like magic you have your rotated image. It's not as bad as it seems for rotations by 90, 180, or -90 degrees, since then the sines and cosines are all +/-1 or 0.
      Still, I know what you're thinking. "No.... Please don't make me do all that! There's got to be a better way!" Well, you're right; there is. The cure for your rotation blues is GDI+. In case you've fallen behind a couple of years in your MSDN® Magazine reading (time flies, I know), GDI+ is the enhanced version of the GDI graphics library, accessible through C++. GDI+ is built into Windows XP and Microsoft .NET, but there's a redistributable for Windows 98, Windows NT®, and Windows 2000. (See http://www.microsoft.com/msdownload/ platformsdk/sdkupdate/psdkredist.htm.)
      GDI+ is a C++ API. It uses C++ classes and methods. To use GDI+ you have to #include <gdiplus.h> and link your project with gdiplus.lib, both of which are part of the latest Windows SDK. GDI+ is much more than I can describe in a wee column here; however, I did rewrite the ImgView program from my October 2001 column into a new program, ImgView2, which shows how to use GDI+ to rotate an image (see Figure 2).

Figure 2 Rotating in ImgView
Figure 2 Rotating in ImgView

      The October column provided a class, CPicture, based on IPicture, the COM interface for manipulating an image. For ImgView2, I rewrote CPicture to use the Image class from GDI+. The conversion was relatively straightforward given that everything was already encapsulated in classes. Once I mapped CPicture to use Image instead of IPicture, all the other classes such as CPictureView and CPictureCtrl worked as before. Naturally, there were a couple of snags.
      The first thing, not a snag really but just a GDI+ requirement, is that you have to initialize and terminate the GDI library. The best place is in your app's InitInstance and ExitInstance functions (see Figure 3). CMyApp::m_gdiplusToken is a magic cookie you get from GdiplusStartup and pass to GdiplusShutdown; m_gdiplusStartupInput is a struct that holds some GDI+ startup parameters, the default constructor for which establishes intelligent default values, demonstrating once again that C++ is better than C.
      Once you've turned on GDI+, you can use it. The old CPicture held a pointer to IPicture; the new one holds a pointer to an Image. As before, there are overloaded Load functions to load a picture from various sources. For example, here's how the new CPicture loads from a path name:
BOOL CPicture::Load(LPCTSTR pszPathName)
{
  Free();
  USES_CONVERSION;
  m_pImage = Image::FromFile(A2W(pszPathName),
    m_bUseEmbeddedColorManagement);
  return m_pImage->GetLastStatus()==Ok;
}
      The main thing here is GDI+ uses wide strings, so you need USES_CONVERSION and A2W. The old CPicture had Load functions to load an image from a CFile, CArchive, resource ID, or stream. All the load functions eventually went to CPicture::Load(IStream*), the one that loads from a stream. But when I began to use Images instead of IPicture, using a GDI+ function to load from streams, nothing worked. Too bad, so sad. The problem turned out to be MFC's CArchiveStream class, the one that implements a stream on a CArchive (see last month's column. For whatever reason—probably CArchiveStream doesn't implement all the IStream methods properly—Image::FromStream doesn't work with a stream based on CArchiveStream. Worst of all, it reports OK, but fails later when you try to display or delete the Image.
      To work around this, I rewrote CPicture::Load(UINT nID) to use CreateStreamOnHGlobal. This handy API function creates a stream on a block of global memory.
// Allocate global memory on which to create stream
HGLOBAL m_hMem = GlobalAlloc(GMEM_FIXED, len);
BYTE* pmem = (BYTE*)GlobalLock(m_hMem);
memcpy(pmem,lpRsrc,len);
IStream* pstm;
CreateStreamOnHGlobal(m_hMem,FALSE,&pstm);
Here lpRsrc already points to the image resource in memory. So the basic idea is to load the image resource, copy it into global memory, create a stream on the memory, and then use Image::FromStream to create an Image. Figure 4 shows the details. CPicture automatically frees the global memory when the object is destroyed or someone loads a different picture. As for loading from CFile or CArchive—well, I never really needed those anyway.
      So much for loading an Image. To display it, you have to use another GDI+ class, Graphics—like a device context (HDC or CDC) in the old GDI—and one of its methods, DrawImage.
BOOL CPicture::Render(CDC* pDC, CRect rc) const
{
  •••
  Graphics graphics(pDC->m_hDC);
  graphics.DrawImage(m_pImage,
    rc.left, rc.top, rc.Width(), rc.Height());
}
      The full details are in Figure 4. Rendering is simpler with Images instead of IPicture: Image::GetWidth and Image::GetHeight get the width and height in pixels, which is what you want instead of the HIMETRIC units you get with IPicture. In general, GDI+ is pretty easy to program. For example, here's how to rotate.
void CPicture::Rotate(RotateFlipType rft)
{
  if (m_pImage) {
    m_pImage->RotateFlip(rft);
  }
}
This rotates the image 90 degrees clockwise. Figure 5 shows the full possibilities for RotateFlipType. GDI+ has other functions to stretch and shear an image. There's even a function Image::GetThumbnailImage to solve your thumbnail problem, which I'll leave for you as a homework exercise.
      I encourage you to explore GDI+. Some programmers don't like it because it's slow, but the documentation has some tips for improving performance. For example, there's a CachedBitmap class that holds a bitmap in a device-optimized format. You probably wouldn't use GDI+ for graphics-intensive applications like a video game or high-end image editor (for those you can use DirectX®), but for everyday graphics tasks, it's a big improvement over GDI.
      Ciao!

Send questions and comments for Paul to cppqa@microsoft.com..
Paul DiLascia is a freelance writer, consultant, and Web/UI designer-at-large. He is the author of Windows++: Writing Reusable Windows Code in C++(Addison-Wesley, 1992). Paul can be reached at askpd@pobox.com or http://www.dilascia.com.

Page view tracker