The Image List

The ImageList component is a collection that holds images of a preset size and color depth. Other controls access pictures in the ImageList using the appropriate index numbers or string key names. In this way, an ImageList acts as a resource for other controls, providing icons for controls like the ToolStrip and TreeView.

ImageList*, ImageIndex*, and ImageKey*

To create an ImageList at design time, drag it onto your form (it will appear in the component tray). The basic members of the ImageList are described in Table 5-2.

Table 5-2. ImageList Members Member Description

ColorDepth A value from the ColorDepth enumeration that identifies the color resolution of the images in the control. Some common choices are 5-bit (256-color mode), 16-bit (high color), and 24-bit (true color).

Images The collection of Image objects that are provided to other controls.

ImageSize A Size structure that defines the size of the contained images (with a maximum of 256 x 256 pixels). ImageList controls should contain only images that share the same size and color depth. Images are converted to the specified format when they are added.

TransparentColor Some image types, like icons and GIFs, define a transparent color that allows the background to show through. By setting the TransparentColor property, you can define a new transparent color that will be used when this image is displayed. This is useful for graphic formats that don't directly support transparency, like bitmaps.

Draw() This overloaded method provides a quick and easy way to take an image and output it to a GDI+ drawing surface.

■Tip Transparent regions are a must when mixing custom images and standard controls. If you simply use an icon with a gray background, your interface becomes garish and ugly on a computer where the default color scheme is not used, as a gray box appears around the image. You also run into problems if the icon can be selected, at which point it is highlighted with a blue background.

You can add, remove, and rearrange images using the ImageList designer. Just click the ellipsis (...) next to the Images property in the Properties window. Images can be drawn from almost any common bitmap file, including bitmaps, GIFs, JPEGs, and icons. When you add a picture, some related read-only properties about its size and format appear in the window (see Figure 5-2).

Figure 5-2. The ImageList designer

Once you have images in an ImageList control, you can use them to provide pictures to another control. Many modern controls provide an ImageList property, which stores a reference to an ImageList control. Individual items in the control (like tree nodes or list rows) then use an ImageIndex property, which identifies a single picture in the ImageList by index number (starting at 0) or an ImageKey property, which identifies a single picture by its string name.

ImageList Serialization

If you look at the automatically generated code for your form, you'll see that the image files you add are stored in a resource file in your project. When the form is created, the images are deserialized into Image objects and placed in the collection. This takes place in the InitializeComponent() helper method that's hidden in the designer file for your form. A special class, the ImageListStreamer, makes this process a simple one-line affair, regardless of how many images are in your ImageList:

this.imagesLarge.ImageStream = ((System.Windows.Forms.ImageListStreamer) (resources.GetObject("imagesLarge.ImageStream")));

Initially, the name is set to match the file name of the original image. However, at no point will your application use the original file. Instead, it uses the embedded binary resource. If you change the picture, you need to remove the image and add it back again (or use resources, which are discussed later in this chapter).

The image key isn't actually stored in the resource file that contains the pictures. Instead, they are applied in the InitializeComponent() method using the SetKeyName() method. Here's an example that shows what takes place:

this.imagesLarge.ImageStream = ((System.Windows.Forms.ImageListStreamer)

(resources.GetObject("imagesLarge.ImageStream"))); this.imagesLarge.Images.SetKeyName(0, "Zapotec.bmp");

Although this might seem to be a fragile approach at first glance, it doesn't cause any problems in practice. If you remove an image or change the order of images using the ImageList designer, Visual Studio updates this code region. You aren't able to change the image content any other way, because the ImageList uses a proprietary serialization format. If you browse the resource file for your form (like Form1.resx for a form named Form1) you'll find the ImageList data is shown as a single opaque binary blob of information.

Manipulating the ImageList in Code

If you want to have an ImageList object around for a longer period (for example, to use in different forms), you can create it directly in code. You might also want to create Image objects out of graphic files rather than use a project resource. First, you need a variable to reference the ImageList:

private ImageList iconlmages = new ImageList();

Then, you can create a method that fills the ImageList:

// Configure the ImageList.

iconlmages.ColorDepth = System.Windows.Forms.ColorDepth.Depth8Bit; iconlmages.ImageSize = new System.Drawing.Size(l6, 16);

// Get all the icon files in the current directory.

string[] iconFiles = Directory.GetFiles(Application.StartupPath, "*.ico");

// Create an Image object for each file and add it to the ImageList. // You can also use an Image subclass (like Icon).

foreach (string iconFile in iconFiles) {

Icon newIcon = new Icon(iconFile); iconImages.Images.Add(newIcon);

Notice that when you use this approach, you no longer have the benefit of the ImageKey property. Although you could set the key names for individual images, it doesn't make much sense to hard-code strings for this purpose if you already need to load the files by hand.

The example that follows loops through an ImageList and draws its images directly onto the surface of a form. The result is shown in Figure 5-3.

// Get the graphics device context for the form. Graphics g = this.CreateGraphics();

// Draw each image using the ImageList.Draw() method.

for (int i = 0; i < iconImages.Images.Count; i++) {

// Release the graphics device context. g.Dispose();

B1 ImageList Example

E0B

p M e o

[ Fill ImageList

1 Draw Images ]

Figure 5-3. Outputting an ImageList directly

As with all manual drawing, these icons are erased as soon as the form is repainted (for example, if you minimize and then maximize it). You'll tackle this issue in Chapter 7.

Limitations of the ImageList

The ImageList may seem like a good all-purpose repository for image data, but it does have a few limitations:

• If you fill the ImageList at design time, you'll need to place it on a single form or on a custom component. That can make it difficult to reuse the same images across multiple windows.

• There's no support for updating the source graphics in the ImageList. When you add the figures to the ImageList, they're copied and no link is maintained to the original files. If you want to change them, you need to delete the image and read it. If you're relying on the ImageIndex property to find images in the ImageList, you'll also need to make sure the order remains the same.

• There's no way to store different sizes and formats of images in the same ImageList. Similarly, the ImageList isn't any help if you want to store other types of content, like audio files.

To tackle these problems, .NET introduces a more powerful alternative—resources.

+1 0

Responses

  • demi-leigh
    What is the task of image list in visual studio?
    1 month ago

Post a comment