Home

VCL Controls: The Image List

 

Introduction

An image list is an array of pictures of the same size. The pictures are created as a single icon or bitmap and each icon or bitmap can be located using its index. The array is zero-based, meaning that the first picture has an index of 0. The second has an index of 1, etc.

An image list is not a traditional control. It does not display to the user who in fact is never aware of it. It is used to complement a control that needs a series of pictures for its own display.

 

The Pictures of an Image List

The image list as a control does not create the necessary images for the list. It only stores them for eventual retrieval. Therefore, before creating a list of images, you must first create the actual pictures that would make up the list. Although Borland Image Editor that ships with C++ Builder on one hand and the Windows Paint that installs with the operating system on the other hand provide good and simple means of creating the pictures, you can use any application that can create and manipulate pictures. Jasc Paint Shop Pro is a good example.

There are two types of lists of pictures you can prepare for an image list. You can create individual pictures that will each be added to the list, one at a time. All pictures should (must) have the same dimensions (same width and same height). Here are examples of such bitmaps:

The second technique consists of creating a single, long picture that contains each of the needed pictures. In this case, you would add this single picture to the image list at once. The picture should (must) provide a series of pictures uniformly dimensioned. You can see an example of a combination of the above pictures.

Image List Creation and Characteristics

The VCL provides support for image lists through the TImageList class. There are two main ways you can create a list of images. If you are setting up a list for icons or small bitmaps that will be used by another control, you can use a friendly dialog box that allows you to create the list. To do this, you would click the ImageList button from the Win32 tab of the Component Palette and add it to your form or other container. To make up the list, you can double-click the icon on the form. This would open the ImageList Editor dialog box where you can easily locate and select the necessary bitmaps or icons. In future lessons, we will use it.

If you are planning to use images that are larger than 32x32 pixels, you should create the control programmatically. To do this, declare a pointer to TImageList. Here is an example:

//---------------------------------------------------------------------------
class TForm1 : public TForm
{
__published: // IDE-managed Components
private:
	TImageList *ImgList; // User declarations
public: // User declarations
	__fastcall TForm1(TComponent* Owner);
};
//---------------------------------------------------------------------------

Before implementing it, use the new operator on its constructor to indicate its owner. This could be done as follows:

//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
	ImgList = new TImageList(this);
}
//---------------------------------------------------------------------------

If you plan to use more than one image list, you can then declare either various TImageList variables (or an array of TImageList variables). An example would be:

//---------------------------------------------------------------------------
class TForm1 : public TForm
{
__published: // IDE-managed Components
private:
	TImageList *SingleImage;
	TImageList *MultiImages; // User declarations
public: // User declarations
	__fastcall TForm1(TComponent* Owner);
};
//---------------------------------------------------------------------------

//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
	: TForm(Owner)
{
	SingleImage = new TImageList(this);
	MultiImages = new TImageList(this);
}
//---------------------------------------------------------------------------

Like other graphics controls, an image list has dimensions. The width of the image list is the width of each one of its pictures. Remember that all pictures must have the same width. The width is set or controlled by the Width property. This would be specified as follows:

//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
	: TForm(Owner)
{
	SingleImage = new TImageList(this);
	Graphics::TBitmap *SingleBitmap = new Graphics::TBitmap;
	SingleImage->Width = 225;

	MultiImages = new TImageList(this);
	Graphics::TBitmap *MultiBitmaps[4];

	MultiBitmaps[0] = new Graphics::TBitmap;
	MultiImages->Width = MultiBitmaps[0]->Width;

	MultiBitmaps[1] = new Graphics::TBitmap;
	MultiImages->Width = MultiBitmaps[1]->Width;
}
//---------------------------------------------------------------------------

The height of an image list is the normal height of each of its pictures. It is set or controlled by the Height property.

There are two kinds of bitmaps or icons that can be used on an image list: masked or nonmasked. A nonmasked image list is made of pictures that each is represented as its own entity. Here is an example:

A masked image list is made of pictures so that each is either doubled or uses two sets of colors. Each picture can be provided in two versions and both versions would represent the same illustration. The first picture is in color and the second would be monochrome. Here is an example:

To indicate that an image list is masked, set the Masked property to true.

After specifying that the image list will use the masked attribute, use the ImageType property to indicate whether the picture is doubled or will use two sets of colors. The possible values of this property derive from the TImageType enumerator whose members are:

Value Description
itImage The picture is single
itMask The picture uses a mask

After specifying that the picture of an image list is masked, when drawing a picture from an image list, you can control what color would serve as its background. This is set or retrieved using the BkColor property. If the Masked property is set to true, the BkColor color would be used to replace the masked sections of the picture.

Image List Methods

To actually create an image list, you must add icons or bitmaps to it. If you are using the Image List Editor dialog box, this is visually done using the buttons on the dialog box. If you are programmatically creating the list of images, you can add each icon or picture individually if they were created as separate entities. You can also add a single long bitmap that is made of various pictures.

To add a bitmap to an image list, call the Add() method. Its syntax is:

int __fastcall Add(Graphics::TBitmap* Image, Graphics::TBitmap* Mask);

The first parameter, Image, is the bitmap you are adding to the list. If the bitmap is masked, specify the bitmap used as the mask for the second argument. If you had set the Masked property to false, the Mask argument would be ignored. This means that you can pass it as NULL.

If the image list is made of a single bitmap, you can simply add it normally. If the list will be created from various separate bitmaps, make sure you add each. Here are examples:

//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
	: TForm(Owner)
{
	MultiImages = new TImageList(this);
	MultiImages->Masked = False;
	Graphics::TBitmap *MultiBitmaps[4];

	MultiBitmaps[0] = new Graphics::TBitmap;
	MultiBitmaps[0]->LoadFromFile("Picture1.bmp");
	MultiImages->Width = MultiBitmaps[0]->Width;
	MultiImages->Height = MultiBitmaps[0]->Height;
	MultiImages->Add(MultiBitmaps[0], NULL);

	. . .

	MultiImages->Height = MultiBitmaps[0]->Height;
}
//---------------------------------------------------------------------------

If you had set the Masked property to true but the bitmap is not doubled, instead of using a color as the mask, call the AddMasked() method. Its syntax is:

int __fastcall AddMasked(Graphics::TBitmap* Image, Graphics::TColor MaskColor);

The Image parameter is the bitmap to add to the list. Once again, the second argument will depend on whether the Masked property is true. If it is, you can pass a MaskColor color to be used to mask the bitmap.

Here is an example:

//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
	: TForm(Owner)
{
	Graphics::TBitmap *SingleBitmap = new Graphics::TBitmap;
	SingleBitmap->LoadFromFile("Picture5.bmp");

	SingleImage = new TImageList(this);
	SingleImage->Width = 225;
	SingleImage->Height = 175;
	SingleImage->Masked = True;
	SingleImage->ImageType = itImage;
	SingleImage->BkColor = clBlack;
	SingleImage->AddMasked(SingleBitmap, clBlack);

	. . .

}
//---------------------------------------------------------------------------

To retrieve the bitmap stored at a specific position in the list, call the GetBitmap() method. Its syntax is:

void __fastcall GetBitmap(int Index, Graphics::TBitmap* Image);

Before calling this method, you should declare a pointer to TBitmap and pass it as the second argument. The Index value indicates the index of the bitmap in the list. If the bitmap exists, it is returned as the Image parameter. Here are examples (and here is the complete source file):

//---------------------------------------------------------------------------

#include <vcl.h>
#pragma hdrstop

#include "Main.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
	: TForm(Owner)
{
	Graphics::TBitmap *SingleBitmap = new Graphics::TBitmap;
	SingleBitmap->LoadFromFile("Picture5.bmp");

	SingleImage = new TImageList(this);
	SingleImage->Width = 225;
	SingleImage->Height = 175;
	SingleImage->Masked = True;
	SingleImage->ImageType = itImage;
	SingleImage->BkColor = clBlack;
	SingleImage->AddMasked(SingleBitmap, clBlack);

	MultiImages = new TImageList(this);
	MultiImages->Masked = False;
	Graphics::TBitmap *MultiBitmaps[4];

	MultiBitmaps[0] = new Graphics::TBitmap;
	MultiBitmaps[0]->LoadFromFile("Picture1.bmp");
	MultiImages->Width = MultiBitmaps[0]->Width;
	MultiImages->Height = MultiBitmaps[0]->Height;
	MultiImages->Add(MultiBitmaps[0], NULL);

	MultiBitmaps[1] = new Graphics::TBitmap;
	MultiBitmaps[1]->LoadFromFile("Picture2.bmp");
	MultiImages->Width = MultiBitmaps[1]->Width;
	MultiImages->Height = MultiBitmaps[1]->Height;
	MultiImages->Add(MultiBitmaps[1], NULL);

	MultiBitmaps[2] = new Graphics::TBitmap;
	MultiBitmaps[2]->LoadFromFile("Picture3.bmp");
	MultiImages->Width = MultiBitmaps[2]->Width;
	MultiImages->Height = MultiBitmaps[2]->Height;
	MultiImages->Add(MultiBitmaps[2], NULL);

	MultiBitmaps[3] = new Graphics::TBitmap;
	MultiBitmaps[3]->LoadFromFile("Picture4.bmp");
	MultiImages->Width = MultiBitmaps[3]->Width;
	MultiImages->Height = MultiBitmaps[3]->Height;
	MultiImages->Add(MultiBitmaps[3], NULL);

	MultiImages->Height = MultiBitmaps[0]->Height;
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Image1Click(TObject *Sender)
{
	static int ImgCounter = 0;

	Graphics::TBitmap *Bmp = new Graphics::TBitmap;

	if( ImgCounter <= SingleImage->Count )
	{
		SingleImage->GetBitmap(ImgCounter++, Bmp);
		Image1->Picture->Bitmap = Bmp;
	}
	else
		ImgCounter = 0;
}
//---------------------------------------------------------------------------
void __fastcall TForm1::FormCreate(TObject *Sender)
{
	Image1Click(Sender); 
	Image2Click(Sender);
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Image2Click(TObject *Sender)
{
	static int ImgCounter = 0;

	Graphics::TBitmap *Bmp = new Graphics::TBitmap;

	if( ImgCounter < MultiImages->Count )
	{
		MultiImages->GetBitmap(ImgCounter++, Bmp);
		Image2->Picture->Bitmap = Bmp;
	}
	else
		ImgCounter = 0;
}
//---------------------------------------------------------------------------

To add an icon to an image list, call the AddIcon() method. Its syntax is:

int __fastcall AddIcon(Graphics::TIcon* Image);

The Image parameter is the icon that needs to be added.

Each of these methods (Add() and AddIcon()) returns the index of the bitmap or icon that was added if the method succeeded. If it fails, it returns 1 indicating that the icon or bitmap was not added.

Once the bitmaps or icons have been added, if you want to find out how many images are in the list, get the TImageList::Count property.

If you want to remove a picture from the image list, call the TImageList::Delete() method. Its syntax:

void __fastcall Delete(int Index);

The Index value is the index of the picture to be removed. Instead of removing a picture, you can just replace it with another picture. This is done using the TImageList::Replace() method whose syntaxes are:

void __fastcall Replace(int Index,
			Graphics::TBitmap* Image,
			Graphics::TBitmap* Mask);

The Index value specifies the index bitmap to replace.

The Image parameter is the new bitmap. If the bitmap is masked, the second parameter, Mask, specifies what bitmap will serve as mask.

If you want to replace an icon, call the ReplaceIcon() method.

Once an image list is ready, you can use it directly in an application or make it available to a control that can use it. One way you can use an image list is to display one or more of its pictures on a form. To do this, you would call the TImageList::Draw() method. It comes in two syntaxes as follows:

void __fastcall Draw(Graphics::TCanvas* Canvas,
                     int X,
                     int Y,
                     int Index,
                     bool Enabled = true);
void __fastcall Draw(Graphics::TCanvas* Canvas,
                     int X,
                     int Y,
                     int Index,
                     TDrawingStyle ADrawingStyle,
                     TImageType AImageType,
                     bool Enabled = true);

The Draw() method is used to draw one of the images on a device context. The Canvas parameter specifies the device on which the bitmap or icon will be drawn.

The X and the Y values are the point location where the drawing would start. That will be the top-left corner of the displaying bitmap or icon.

The Index parameter specifies the index of the picture to be drawn, from the list of images. The list is zero-based, meaning the first image has an index of 0, the second is 1, etc.

Here is an example:

 

//---------------------------------------------------------------------------
void __fastcall TForm1::Image2Click(TObject *Sender)
{
	static int ImgCounter = 0;

	Graphics::TBitmap *Bmp = new Graphics::TBitmap;

	if( ImgCounter < MultiImages->Count )
	{
		MultiImages->GetBitmap(ImgCounter, Bmp);
		// Image2->Picture->Bitmap = Bmp;
		MultiImages->Draw(this->Canvas, Image2->Left, 
		Image2->Top, ImgCounter);
		ImgCounter++;
	}
	else
		ImgCounter = 0;
}
//---------------------------------------------------------------------------
Home Copyright 2005-20007 FunctionX, Inc.