Image ListsImage Lists*
*Contents  *Index  *Topic Contents
*Previous Topic: HKM_SETRULES
*Next Topic: Image List Reference

Image Lists


An image list is a collection of images of the same size, each of which can be referred to by its index. Image lists are used to efficiently manage large sets of icons or bitmaps. All images in an image list are contained in a single, wide bitmap in screen device format. An image list can also include a monochrome bitmap that contains masks used to draw images transparently (icon style).

arrowy.gifUsing Image Lists

arrowy.gifImage List Updates in Internet Explorer

arrowy.gifImage List Reference

Using Image Lists

The Microsoft® Win32® application programming interface (API) provides image list functions that enable you to create and destroy image lists, add and remove images, replace and merge images, draw images, and drag images.

To use the image list functions, include the common control header file in your source code files and link with the common control export library. In addition, before calling any image list function, use the InitCommonControls function to ensure that the common control dynamic-link library (DLL) is loaded.

Types

There are two types of image lists: nonmasked and masked. A nonmasked image list consists of a color bitmap that contains one or more images. A masked image list consists of two bitmaps of equal size. The first is a color bitmap that contains the images, and the second is a monochrome bitmap that contains a series of masks—one for each image in the first bitmap.

When a nonmasked image is drawn, it is simply copied into the target device context; that is, it is drawn over the existing background color of the device context. When a masked image is drawn, the bits of the image are combined with the bits of the mask, typically producing transparent areas in the bitmap where the background color of the target device context shows through. There are several drawing styles that you can specify when drawing a masked image. For example, you can specify that the image be dithered to indicate a selected object.

Creating and Destroying Image Lists

You create an image list by calling the ImageList_Create function. The parameters include the type of image list to create, the dimensions of each image, and the number of images you intend to add to the list. For a nonmasked image list, the function creates a single bitmap large enough to hold the specified number of images of the given dimensions. Then it creates a screen-compatible device context and selects the bitmap into it. For a masked image list, the function creates two bitmaps and two screen-compatible device contexts. It selects the image bitmap into one device context and the mask bitmap into the other. The common control DLL contains the executable code for the image list functions.

In ImageList_Create, you specify the initial number of images that will be in an image list as well as the number of images by which the list can grow. So if you attempt to add more images than you initially specified, the image list automatically grows to accommodate the new images.

If ImageList_Create succeeds, it returns a handle to the HIMAGELIST type. You use this handle in other image list functions to access the image list and manage the images. You can add and remove images, copy images from one image list to another, and merge images from two different image lists. When you no longer need an image list, you can destroy it by specifying its handle in a call to the ImageList_Destroy function.

The following example creates a masked image list and uses the ImageList_AddIcon function to add two icons to the list.

	// AddIconsToImageList - creates a masked image list and adds some 
	//     icons to it. 
	// Returns the handle to the new image list. 
	// hinst - handle to the application instance. 
	// 
	// Global variables and constants 
	//     g_nBird and g_nTree - indexes of the images. 
	//     cx_icon and cy_icon - width and height of the icon. 
	//     num_icons - number of icons to add to the image list. 
	extern int g_nBird, g_nTree; 
	 
	#define CX_ICON  32 
	#define CY_ICON  32 
	#define NUM_ICONS 3 
	 
	HIMAGELIST AddIconsToImageList(HINSTANCE hinst) 
	{ 
	    HIMAGELIST himlIcons;  // handle to new image list 
	    HICON hicon;           // handle to icon 
	 
	    // Ensure that the common control DLL is loaded. 
	    InitCommonControls(); 
 
    // Create a masked image list large enough to hold the icons. 
    himlIcons = ImageList_Create(CX_ICON, CY_ICON, TRUE, NUM_ICONS, 0); 
 
    // Load the icon resources, and add the icons to the image list. 
    hicon = LoadIcon(hinst, MAKEINTRESOURCE(IDI_BIRD)); 
    g_nBird = ImageList_AddIcon(himlIcons, hicon); 
 
    hicon = LoadIcon(hinst, MAKEINTRESOURCE(IDI_TREE)); 
    g_nTree = ImageList_AddIcon(himlIcons, hicon); 
 
	    return himlIcons; 
	} 
 

Adding and Removing Images

You can add bitmapped images, icons, or cursors to an image list. You add bitmapped images by specifying the handles to two bitmaps in a call to the ImageList_Add function. The first bitmap contains one or more images to add to the image bitmap, and the second bitmap contains the masks to add to the mask bitmap. For nonmasked image lists, the second bitmap handle is ignored; it can be set to NULL.

The ImageList_AddMasked function also adds bitmapped images to a masked image list. This function is similar to ImageList_Add, except that you do not specify a mask bitmap. Instead, you specify a color that the system combines with the image bitmap to automatically generate the masks. Each pixel of the specified color in the image bitmap is changed to black, and the corresponding bit in the mask is set to 1. As a result, any pixel in the image that matches the specified color is transparent when the image is drawn.

The ImageList_AddIcon function adds an icon or cursor to an image list. If the image list is masked, ImageList_AddIcon adds the mask provided with the icon or cursor to the mask bitmap. If the image list is nonmasked, the mask for the icon or cursor is not used when drawing the image.

You can create an icon based on an image and mask in an image list by using the ImageList_GetIcon function. The function returns the handle to the new icon.

ImageList_Add, ImageList_AddMasked, and ImageList_AddIcon assign an index to each image as it is added to an image list. The indexes are zero-based; that is, the first image in the list has an index of zero, the next has an index of one, and so on. After adding a single image, the functions return the index of the image. When more than one image is added at a time, the functions return the index of the first image.

The ImageList_Remove function removes an image from an image list.

Replacing and Merging Images

The ImageList_Replace and ImageList_ReplaceIcon functions replace an image in an image list with a new image. ImageList_Replace replaces an image with a bitmapped image and mask, and ImageList_ReplaceIcon replaces an image with an icon or cursor.

The ImageList_Merge function merges two images, storing the new image in a new image list. The new image is created by drawing the second image transparently over the first. The mask for the new image is the result of performing a logical OR operation on the bits of the masks for the two existing images.

Drawing Images

To draw an image, you use the ImageList_Draw or ImageList_DrawEx function. You specify the handle to an image list, the index of the image to draw, the handle to the destination device context, a location within the device context, and one or more drawing styles.

When you specify the ILD_TRANSPARENT style, ImageList_Draw or ImageList_DrawEx uses a two-step process to draw a masked image. First, it performs a logical AND operation on the bits of the image and the bits of the mask. Then it performs a logical XOR operation on the results of the first operation and the background bits of the destination device context. This process creates transparent areas in the resulting image; that is, each white bit in the mask causes the corresponding bit in the resulting image to be transparent.

Before drawing a masked image on a solid color background, you should use the ImageList_SetBkColor function to set the background color of the image list to the same color as the destination. Setting the color eliminates the need to create transparent areas in the image and enables ImageList_Draw or ImageList_DrawEx to simply copy the image to the destination device context, resulting in a significant increase in performance. To draw the image, specify the ILD_NORMAL style in a call to ImageList_Draw or ImageList_DrawEx.

You can set the background color for a masked image list at any time so that it draws correctly on any solid background. Setting the background color to CLR_NONE causes images to be drawn transparently by default. To retrieve the background color of an image list, use the ImageList_GetBkColor function.

The ILD_BLEND25 and ILD_BLEND50 styles dither the image with the system highlight color. These styles are useful if you use a masked image to represent an object that the user can select. For example, you can use the ILD_BLEND50 style to draw the image when the user selects it.

A nonmasked image is copied to the destination device context using the SRCCOPY raster operation. The colors in the image appear the same regardless of the background color of the device context. The drawing styles specified in ImageList_Draw or ImageList_DrawEx also have no effect on the appearance of a nonmasked image.

Drawing the image

The following function draws an image and saves the client coordinates of the image's bounding rectangle. A subsequent function uses the bounding rectangle to determine whether the user has clicked the image.

	// DrawTheImage - draws an image transparently and saves 
	//     the bounding rectangle of the drawn image.
	// Returns TRUE if successful, or FALSE otherwise. 
	// hwnd - handle to the window in which to draw the image. 
	// himl - handle to the image list that contains the image. 
	// cx and cy - client coordinates for the upper-left corner of the image. 
	// 
	// Global variables and constants 
	//     g_nImage - index of the image to draw. 
	//     g_rcImage - bounding rectangle of the image. 
	//     CX_IMAGE and CY_IMAGE - width and height of the image. 
	extern int g_nImage; 
	extern RECT g_rcImage; 
	 
	#define CX_IMAGE 32 
	#define CY_IMAGE 32 
 
	BOOL DrawTheImage(HWND hwnd, HIMAGELIST himl, int cx, int cy) 
	{ 
	    HDC hdc; 
 
	    if ((hdc = GetDC(hwnd)) == NULL) 
	        return FALSE; 
	    if (!ImageList_Draw(himl, g_nImage, hdc, cx, cy, ILD_TRANSPARENT)) 
	        return FALSE; 
	    ReleaseDC(hwnd, hdc); 
 
	    SetRect(&g_rcImage, cx, cy, CX_IMAGE + cx, CY_IMAGE + cy); 
 
	    return TRUE; 
	} 

Dragging Images

The Win32 API includes functions for dragging an image on the screen. The dragging functions move an image smoothly, in color, and without any flashing of the cursor. Both masked and unmasked images can be dragged.

The ImageList_BeginDrag function begins a drag operation. The parameters include the handle to the image list, the index of the image to drag, and the location of the hot spot within the image. The hot spot is a single pixel that the dragging functions recognize as the exact screen location of the image. Typically, an application sets the hot spot so that it coincides with the hot spot of the mouse cursor. The ImageList_DragMove function moves the image to a new location.

The ImageList_DragEnter function sets the initial position of the drag image within a window and draws the image at the position. The parameters include the handle to the window in which to draw the image and the coordinates of the initial position within the window. The coordinates are relative to the window's upper-left corner, not the client area. The same is true for all of the image dragging functions that take coordinates as parameters. This means you must compensate for the widths of window elements such as the border, title bar, and menu bar when specifying the coordinates. If you specify a NULL window handle when calling ImageList_DragEnter, the dragging functions draw the image in the device context associated with the desktop window, and the coordinates are relative to the upper-left corner of the screen.

ImageList_DragEnter locks all other updates to the given window during the drag operation. If you need to do any drawing during a drag operation, such as highlighting the target of the operation, you can temporarily hide the dragged image by using the ImageList_DragLeave function. Another method is to use the GetDCEx function with the DCX_LOCKWINDOWUPDATE value to retrieve a device context that allows you to draw. Be careful, however, not to obliterate the dragged image.

The ImageList_SetDragCursorImage function creates a new drag image by combining the given image (typically a mouse cursor image) with the current drag image. Because the dragging functions use the new image during a drag operation, you should use the ShowCursor function to hide the actual mouse cursor after calling ImageList_SetDragCursorImage. Otherwise, the system may appear to have two mouse cursors for the duration of the drag operation.

When an application calls ImageList_BeginDrag, the system creates a temporary, internal image list and then copies the specified drag image to the internal list. You can retrieve the handle to the temporary drag image list by using the ImageList_GetDragImage function. The function also retrieves the current drag position and the offset of the drag image relative to the drag position.

Beginning the drag operation

The following function is intended to be called in response to a mouse button-down message, such as WM_LBUTTONDOWN. The function determines whether the user has clicked within the bounding rectangle of the image. If the user has clicked, the function captures the mouse input, erases the image from the client area, and calculates the position for the hot spot within the image. The function sets the hot spot to coincide with the hot spot of the mouse cursor. Then the function begins the drag operation by calling ImageList_BeginDrag.

	// StartDragging - begins dragging a bitmap. 
	// Returns TRUE if successful, or FALSE otherwise. 
	// hwnd - handle to the window in which the bitmap is dragged. 
	// ptCur - coordinates of the cursor. 
	// himl - handle to the image list. 
	// 
	// Global variables 
	//     g_rcImage - bounding rectangle of the image to drag. 
	//     g_nImage - index of the image. 
	//     g_ptHotSpot - location of the image's hot spot. 
	//     g_cxBorder and g_cyBorder - width and height of border. 
	//     g_cyCaption and g_cyMenu - height of title bar and menu bar. 
	extern RECT g_rcImage; 
	extern int g_nImage; 
	extern POINT g_ptHotSpot; 
	 
	BOOL StartDragging(HWND hwnd, POINT ptCur, HIMAGELIST himl) 
	{ 
	    // Return if the cursor is not in the bounding rectangle of 
	    // the image. 
    if (!PtInRect(&g_rcImage, ptCur)) 
        return FALSE; 
 
    // Capture the mouse input. 
    SetCapture(hwnd); 
 
    // Erase the image from the client area. 
    InvalidateRect(hwnd, &g_rcImage, TRUE); 
    UpdateWindow(hwnd); 
 
    // Calculate the location of the hot spot, and save it. 
    g_ptHotSpot.x = ptCur.x - g_rcImage.left; 
    g_ptHotSpot.y = ptCur.y - g_rcImage.top; 
 
    // Begin the drag operation. 
    if (!ImageList_BeginDrag(himl, g_nImage, 
            g_ptHotSpot.x, g_ptHotSpot.y)) 
        return FALSE; 
 
    // Set the initial location of the image, and make it visible. 
    // Because the ImageList_DragEnter function expects coordinates to 
    // be relative to the upper-left corner of the given window, the 
    // width of the border, title bar, and menu bar need to be taken 
    // into account. 
    ImageList_DragEnter(hwnd, ptCur.x + g_cxBorder, 
        ptCur.y + g_cyBorder + g_cyCaption + g_cyMenu); 
 
    g_fDragging = TRUE; 
 
	    return TRUE; 
	} 

Moving the image

The following function, which drags the image to a new location, is intended to be called in response to the WM_MOUSEMOVE message.

	// MoveTheImage - drags an image to the specified coordinates. 
	// Returns TRUE if successful, or FALSE otherwise. 
	// ptCur - new coordinates for the image. 
	BOOL MoveTheImage(POINT ptCur) 
	{ 
	    if (!ImageList_DragMove(ptCur.x, ptCur.y)) 
        return FALSE; 
 
    return TRUE; 
	} 

Ending the drag operation

The following function ends the drag operation and draws the image in its final location. It also releases the mouse capture.

	// StopDragging - ends a drag operation and draws the image 
	//     at its final location. 
	// Returns TRUE if successful, or FALSE otherwise. 
	// hwnd - handle to the window in which the bitmap is dragged. 
	// himl - handle to the image list. 
	// ptCur - coordinates of the cursor. 
	// 
	// Global variable 
	//     g_ptHotSpot - location of the image's hot spot. 
 
	extern POINT g_ptHotSpot; 
 
	BOOL StopDragging(HWND hwnd, HIMAGELIST himl, POINT ptCur) 
	{ 
    ImageList_EndDrag(); 
    ImageList_DragLeave(hwnd) 
 
    g_fDragging = FALSE; 
 
    DrawTheImage(hwnd, himl, ptCur.x - g_ptHotSpot.x, 
        ptCur.y - g_ptHotSpot.y); 
 
    ReleaseCapture(); 
	    return TRUE; 
	} 

Image Information

There are a number of functions that retrieve information from an image list. The ImageList_GetImageInfo function fills an IMAGEINFO structure with information about a single image, including the handles of the image and mask bitmaps, the number of color planes and bits per pixel, and the bounding rectangle of the image within the image bitmap. You can use this information to directly manipulate the bitmaps for the image. The ImageList_GetImageCount function retrieves the number of images in an image list.

Image Overlays

Every image list includes a list of indexes to use as overlays. An overlay is an image that is drawn transparently over another image. Any image currently in the image list can be used as an overlay. You can specify up to four overlays per image list. This limit has been expanded to 15 in version 4.71.

You add the index of an image to the list of overlays by using the ImageList_SetOverlayImage function, specifying the handle to the image list, the index of the existing image, and the desired overlay index. This, in effect, tells the image list that "the image at index x can be used as an overlay, and I want to refer to the overlay as overlay index y." The overlay indexes are one-based rather than zero-based because an overlay index of zero means that no overlay will be used.

You specify an overlay when drawing an image with the ImageList_Draw or ImageList_DrawEx function. The overlay is specified by performing a logical OR operation between the desired drawing flags and the result of the INDEXTOOVERLAYMASK macro. The INDEXTOOVERLAYMASK macro takes the overlay index and formats it for inclusion with the flags for these functions. This will draw the image with the specified overlay. The following example demonstrates how an overlay is added and specified when drawing the image.

ImageList_SetOverlayImage(himl, 0, 3);
ImageList_Draw(himl, 1, hdc, 0, 0, ILD_MASK | INDEXTOOVERLAYMASK(3));

This will draw image 1 and then overlay that image with image 0. Because 3 is the overlay index that you specified in the ImageList_SetOverlayImage call, 3 is placed in the INDEXTOOVERLAYMASK macro.

Image List Updates in Internet Explorer

The following features were added to the image list by Microsoft® Internet Explorer.

Copying Images
Copy or swap images within an image list using the ImageList_Copy function. This function allows you to indicate whether the source image should be copied to the destination index or the source and destination images should be swapped. Currently, this is allowed only within a single image list.
Duplicating Image Lists
Take an existing image list and duplicate all of its parameters and contents into a new image list using the ImageList_Duplicate function. The image list returned by this function is an exact duplicate of the original image list and must be destroyed separately. Changes made to one image list do not affect the other.
Dynamic Resizing of Image Lists
Modify the number of images in an image list on the fly using the ImageList_SetImageCount function. If the number of images is increased, you must use the ImageList_Replace function to place images in the added slots. If the number of images is reduced, the images beyond the new size are freed and are no longer available.
Extended Drawing of Images
You now have more control over the drawing of images with the ImageList_DrawIndirect function. This function takes an IMAGELISTDRAWPARAMS structure that specifies the details that will be used when drawing the image. With this function, you can now specify things like ROP codes when drawing.

Up Top of Page
© 1997 Microsoft Corporation. All rights reserved. Terms of Use.