Image lists can be used to store collections of bitmaps, making them useful when several bitmaps are needed, such as in tree view and list view controls. In this hour, you learn
Also, in this hour you will build a sample program that creates an image list and uses it as a storage location for bitmap images. This hour will build a foundation that you will use later in Hour 18, "List View Controls," and Hour 19, "Tree Views."
An image list is similar to an array of bitmaps, just like a roll of film is an array of images, as shown in Figure 17.1. Unlike rolls of film, an image list can grow, if needed, as extra images are added to the list. Each bitmap stored in an image list is associated with an index, which can be used to retrieve a particular image.
Figure 17.1.
An image list is like a roll of bitmap images.
Time Saver: Image lists can also be used outside these new controls, and they provide an easy way to store a series of bitmaps, because you must handle only a single image-list object instead of separate objects for each bitmap.
If you want to display bitmaps in tree views or list views, you must use an image list. If your program needs to manage several different bitmapped images, a single image list is easier to use than a series of bitmaps. Accessing and displaying multiple images from an image list is much easier than handling multiple CBitmap objects. Windows Explorer has a much richer user interface than the older File Manager used in Windows 3.1. Much of this richness is achieved through the use of image lists, which offer an easy way to store and manage bitmaps.
In addition, image lists offer two features that are difficult to duplicate with regular bitmaps:
New Term: A transparent image is an image that allows the background to be seen through part of the image, as if part of the bitmap were transparent.
A transparent image is difficult to achieve using a normal bitmap. In the simplest cases, about twice as many lines of code are required to draw a bitmap transparently as are required to draw it as an opaque image against a drawing surface. Using an image list, drawing a transparent bitmap is almost effortless, requiring little more than parameters that are set correctly.
New Term: An overlaid image is created by combining two images to form a single, combined image.
An overlaid image is useful when showing special attributes for items represented by images stored in an image list. For example, when a shared directory is shown in the Explorer, a server "hand" is superimposed over the directory's folder. This is an overlaid image.
As for almost everything else in Windows, there is an MFC class for image lists, too. The CImageList class is used to create, display, and otherwise manage image lists in an MFC-based Windows program.
Image lists often are used to provide item images for the CListCtrl class that is covered in Hour 18, and the CTreeCtrl class that is covered in Hour 19. However, you can also use an image list as a collection of bitmaps, which you will do in this chapter. Using image lists in this way helps show off the different things you can do with image lists before they are used with the common controls.
As an example of using image lists, create an SDI project named ImageList. This project uses an image list to display a series of bitmaps in the program's client area.
The first step in creating an image list is to create a series of bitmaps, each of which is the same size. Although the images can be any size, the sample code in this section assumes the bitmaps are 32 pixels on each side. The bitmaps used in the example are shown in Figure 17.2.
Figure 17.2.
The bitmaps used in the ImageList example are all the same size.
Create the three bitmaps, and name them as shown in Table 17.1.
ID | Description |
IDB_CROSS | Cross mark |
IDB_CHECK | Check mark |
IDB_BANG | Exclamation point |
Storing a bitmap image in an image list consists of three steps:
The bitmap object is deleted because the image list makes a copy of the bitmap and stores the image internally. As a rule of thumb, any time a Windows GDI object is loaded, it should be deleted to prevent memory leaks. The preceding steps are handled by AddBitmapToImageList, a new function added to the CImageListView class. Add the function provided in Listing 17.1 to the ImageListView.cpp source file.
BOOL CImageListView::AddBitmapToImageList( UINT nResourceID ) { BOOL bReturn; CBitmap bmp; bReturn = bmp.LoadBitmap( nResourceID ); if( bReturn != FALSE ) { int nReturn = m_imageList.Add( &bmp, RGB(255,255,255) ); bmp.DeleteObject(); } return bReturn;
} The AddBitmapToImageList function is used because three bitmap resources are added to the image list. Adding the bitmaps using a new member function reduces the amount of code you must write and helps reduce the chance of errors, because every bitmap is loaded using the same function.
The CImageList::Add member function is used to add an image to the image list. The version of Add used in Listing 17.1 takes two parameters:
Time Saver: The background color is used when drawing transparent images using masked bitmaps. If you aren't using a masked image list, the COLORREF value is ignored.
After adding the member function to the ImageListView.cpp file, add the source code from Listing 17.2 to the CImageListView class, found in the file ImageListView.h. Add the source code in the class implementation section, which is marked by the // Implementation comment. After the comment, there is a protected: label inserted by AppWizard for user- supplied variables and functions.
protected: BOOL AddBitmapToImageList( UINT nResourceID );
CImageList m_imageList; The actual work of creating the image list is done when the view is constructed. The image list can be built at any time; however, it is costly to create an image list in terms of computing power. Creating the image list in the constructor lets you build it once, rather than each time it is used. Add the source code from Listing 17.3 to the constructor for CImageViewList.
CImageListView::CImageListView() { m_imageList.Create( 32, 32, TRUE, 3, 1 ); AddBitmapToImageList( IDB_CROSS ); AddBitmapToImageList( IDB_CHECK ); AddBitmapToImageList( IDB_BANG );
} The image list is created using one of the CImageList::Create functions. This version of Create is useful when an image list is used as a bitmap collection; I use other versions of Create in the following chapters. This version of Create has five parameters:
New Term: A masked image list is an image list that contains two bitmaps for each image--the second bitmap is a mask that is used when drawing transparent images. Parts of the image that are visible are colored black in the mask, parts that are transparent are colored white in the mask.
Individual items stored in an image list can be drawn using the CImageList::Draw member function, as shown in Listing 17.4.
void CImageListView::OnDraw(CDC* pDC) { CPoint ptImage( 0, 0 ); for( int nImage = 0; nImage < 3; nImage++ ) { m_imageList.Draw( pDC, nImage, ptImage, ILD_NORMAL ); ptImage.x += 50; }
} The Draw member function has four parameters:
Compile and run the ImageList project. Figure 17.3 shows the current version of the ImageList application running.
Figure 17.3.
Using ILD_NORMAL to display the contents of the image list.
There are eight different types of drawing operations:
Figure 17.4 shows the image list items drawn using the ILD_MASK style. This allows you to see the image mask generated by the image list.
Figure 17.4.
Image list items mask drawn using ILD_MASK.
The individual image bitmaps stored in an image list can also be extracted as icons using the ExtractIcon member function:
HICON hicon = m_imageList.ExtractIcon( nImage );
The only parameter needed for ExtractIcon is the image index. You can then use the icon extracted just like any icon handle. Icons were discussed in Hour 14, "Icons and Cursors."
There are two methods you can use to display an image transparently:
A simple method for drawing a transparent image is to define the background color that is used on the image background. The background color of the image list will then be adjusted to match the surface background color, allowing the drawing surface to "shine through," giving the image a transparent effect. Replace the CImageList::OnDraw function with the code provided in Listing 17.5, and then recompile and run the ImageList program.
void CImageListView::OnDraw(CDC* pDC) { m_imageList.SetBkColor( RGB(0,255,0) ); CPoint ptImage( 0, 0 ); for( int nImage = 0; nImage < 3; nImage++ ) { m_imageList.Draw( pDC, nImage, ptImage, ILD_NORMAL); ptImage.x += 50; }
} If you compile and run the ImageList project, the background of the images will be set to green. By changing the RGB COLORREF value passed to the CImageList::SetBkColor function, you can match any background color.
Another transparent drawing method is to use the ILD_TRANSPARENT flag when CImageList::Draw is called. This tells the image list to combine the image mask with the bitmap, if a mask exists. If the image list is not masked, the image is drawn as if ILD_NORMAL was used.
An overlapped image is two images from the same bitmap, with one image superimposed on the other. Before using an image as an overlay, it must be defined as an overlay image. You can define up to four bitmaps per image list as overlays using the CImageList::SetOverlayImage function:
m_imageList.SetOverlayImage( 0, 1 );
The SetOverlayImage function takes two parameters: the image index used as the overlay, and the overlay index used to identify the overlay.
Just a Minute: Just to make things more interesting, unlike almost every other index used in Windows, the overlay index starts at one instead of zero.
To use an overlaid image, the CImageList::Draw function is used as in previous examples, except that the ILD_OVERLAYMASK flag is used. The INDEXTOOVERLAYMASK macro is combined with the ILD_OVERLAYMASK flag to specify the overlay image index to be combined with the base image. Listing 17.6 is a new version of OnDraw that displays an overlaid image using an image list.
void CImageListView::OnDraw(CDC* pDC) { m_imageList.SetBkColor( CLR_NONE ); CPoint ptOverlay( 50, 80 ); m_imageList.SetOverlayImage( 0, 1 ); m_imageList.Draw( pDC, 2, ptOverlay, INDEXTOOVERLAYMASK(1) ); }
In this chapter, you learned about image lists, a convenient way to display images in a Windows program. You used image lists to draw a series of bitmaps that were opaque, transparent, or overlaid with a second image.
nReturn = m_imageList.Add( &bmpImage, &bmpMask );
nReturn = m_imageList.Add( hIcon );
The Workshop is designed to help you anticipate possible questions, review what you've learned, and begin thinking ahead to putting your knowledge into practice. The answers to the quiz are in Appendix B, "Quiz Answers."
© Copyright, Macmillan Computer Publishing. All rights reserved.