Home

Bitmaps

 

Bitmaps Fundamentals

 

Introduction

A bitmap is a graphic object used to display a picture on a window or to store it in the computer memory as a file. It is the primary type of graphics used for various occasions. For example, a bitmap can be used as a background for a window. That is the case for the Pinball game that ships with some versions of Microsoft Windows:

 

A bitmap can also be used for aesthetic purposes to decorate a dialog box. That’s how it is used on some of the installation wizard boxes such as the graphic on the left section of the WordPerfect 2002 installer:

Probably the most regular use of bitmaps is as small graphics on toolbars:

There are three main ways you create or add a bitmap to your application. You can create an array of byte values that describe the bitmap. You can design a bitmap using a low-level bitmap application like Image Editor, or you can use a professional picture.

Bitmap Creation

There are three types of bitmaps we will be creating for our lessons. The simplest consists of designing a regular picture made of regular colors from the Image Editor. Another technique consists of declaring an array of bits that describes the bitmap; then translate this array into a handle to bitmap before actually using it. The last technique, which requires some design or importing, consists of using a more advance picture in an application.

Creating a bitmap and making it available to an application is just one aspect. The goal is to use such a bitmap or to decide what to use it for. Normally, the way you create a bitmap has some influence on where and how that bitmap is used. For example, bitmaps created in Image Editor using only its tools are appropriate to display on top of controls that need small bitmaps. Those bitmaps and those created from an array of bits are also the prime candidates to use as drawing brushes. Bitmaps that are professional looking pictures and that tend to be taller or wider are usually used to display illustrative pictures. In reality, any of the bitmaps can be used in any scenario of your choice.

Bitmap Design on Image Editor

Image Editor provides a good environment to create small bitmaps that would be used on controls that need them. Such bitmaps usually have a size of 16x16 pixels, 32x32 pixels, or a ratio of width and height appropriate for the control that needs the bitmap. We will use bitmaps on bitmap buttons, toolbars, and list-based controls, etc.

To create a bitmap, on the main menu of Image Editor, you would click File -> New -> Bitmap File (.bmp). A dialog box would come up. This allows you to specify the possible dimensions of the picture. You can specify the dimensions of your choice according to the intended eventual use of the bitmap.

You can also get a bitmap by changing an existing picture. To modify an existing picture, you can use any graphics software that is fit. Windows Paint that ships with the operating system is a good cheap alternative to commercial applications. Jasc Paint Shop Pro is also an excellent product suitable to do almost anything with a bitmap. To manipulate a bitmap with such applications, you should first import it. On the main menu of Windows Paint, you can click File -> Open… Change the Files of Type to the kind of file you want to open, or set it to All Files. Locate the desired file and click Open. Alternatively, you can find a way to copy the graphic and paste it into Windows Paint.

After designing your bitmap, you must save it. A bitmap is a Windows file that has an extension of .bmp

Practical Learning Practical Learning: Creating a Bitmap

  1. To launch Image Editor, on the taskbar, click Start -> (All) Programs -> Borland C++ Builder -> Image Editor
  2. On the main menu of Image Editor, click File -> New… -> Bitmap(.bmp)
  3. On the Bitmap Properties dialog box, set the both the Width and Height values to 32
  4. On the Colors section, click the VGA (16 colors) radio button
     
  5. Click OK
  6. Click Ctrl + I a few times until the height of the drawing area is the same as the height of the child window
  7. Using the tools on the Toolbox and the colors on the Colors Palette, design the bitmap as follows:
     
  8. Save it as Diamond1

Bitmap Creation: Windows Paint

Paint (or PaintBrush) is an application that gets installed with Microsoft Windows. It provides a cheap solution to creating or maipulating bitmaps. It is a little more flexible than Image Editor. For example, if you try opening a color-intensive picture in Image Editor, you would receive an error:

The same picture can be opened in Paint:

Of course an alternative is to open the picture in another application such as Paint, select then copy it to the clipboard, and then paste it in Image Editor.

One of the differences between both applications is that when creating a new bitmap in Image Editor, you must specify its size. After doing this, if you paste an image that is wider or taller than the allocated rectangle, part of the picture would not appear. You would then have to resize the rectangle and paste again. In Paint, if you attempt to paste an image that is wider and/or taller than the primarily allocated rectangle, you would be asked whether you want the rectangle to be resized to accommodate the picture.

Based on this review, if you are creating a bitmap that would be displayed on top of Windows controls that need small pictures (bitmap buttons, list view, tree view, etc) use Image Editor to prepare them. If you are preparing an advanced picture to use in your application, you should use either Paint or a more advanced graphic editor. C++ Builder does not care where or how you created a bitmap as long as it is in the right format (either bmp, jpeg, or jpg extension).

The VCL Support of Bitmaps

 

Introduction

The VCL provides support for bitmaps through the TBitmap class from the Graphics namespace. Some classes, such as TBrush, already have a Bitmap member variable that you can use initialize appropriately. In most cases, you will need to declare a pointer to TBitmap. To do this, you must precede the name of the class with the Graphics namespace. Here is an example:

//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
	: TForm(Owner)
{
	Graphics::TBitmap *LaCourt = new Graphics::TBitmap;
}
//---------------------------------------------------------------------------

Like all other dynamic objects, after using the bitmap, you should delete it. If you declare it locally, you can also delete it in the same event or method. Here is an example:

//---------------------------------------------------------------------------
void __fastcall TForm1::FormDblClick(TObject *Sender)
{
	Graphics::TBitmap *BmpMercedes = new Graphics::TBitmap;

	try {
		// Treat the bitmap file here
	}
	__finally
	{
		// Time to delete the pointer
		delete BmpMercedes;
	}
}
//---------------------------------------------------------------------------

If you declare it globally, make sure you delete it when the application is destroyed. After declaring the variable, you must initialize it appropriately before actually using it.

Bitmap Drawing

Once the file is ready, you can use it in your application. For example, you can display it on a form. Because the form is equipped with a canvas, to display a picture, you can call the TCanvas::Draw() method. Its syntax is:

void __fastcall Draw(int X, int Y, TGraphic* Graphic);

The X and Y values specify the corner from where to start drawing. Normally, it will be the top-left coordinates of the picture. The Graphic parameter is the graphic file to draw on the canvas. This would be done as follows:

//---------------------------------------------------------------------------
void __fastcall TForm1::FormDblClick(TObject *Sender)
{
	Graphics::TBitmap *BmpMercedes = new Graphics::TBitmap;

	try {
		Canvas->Draw(10, 10, BmpMercedes);
	}
	__finally
	{
		delete BmpMercedes;
	}
}
//---------------------------------------------------------------------------

Bitmap Loading From a File

In order to use a bitmap in your application, you must import it from its file to the application. The easiest way to do this consists of calling the TGraphic::LoadFromFile() method. Its syntax is:

virtual void __fastcall LoadFromFile(const AnsiString FileName);

This method is particularly easy to use as long as you know the location of the bitmap file. If the picture is in the same directory as the current project, you can simply type its name and its extension as a string and pass it as argument. An example would be:

//---------------------------------------------------------------------------
void __fastcall TForm1::FormDblClick(TObject *Sender)
{
	Graphics::TBitmap *BmpMercedes = new Graphics::TBitmap;

	try {
		BmpMercedes->LoadFromFile("Mercedes2.bmp");
		Canvas->Draw(10, 10, BmpMercedes);
	}
	__finally
	{
		delete BmpMercedes;
	}
}
//---------------------------------------------------------------------------

If the file is not in the same directory as the project, you may have to specify its complete path. Here is an example:

//---------------------------------------------------------------------------
void __fastcall TForm1::FormDblClick(TObject *Sender)
{
	Graphics::TBitmap *BmpMercedes = new Graphics::TBitmap;

	try {
		BmpMercedes->LoadFromFile("C:\\Programs\\Mercedes1.bmp");
		Canvas->Draw(10, 10, BmpMercedes);
	}
	__finally
	{
		delete BmpMercedes;
	}
}
//---------------------------------------------------------------------------

If the file, its path, and its extension are correct, the file can be used:

If the file does not exist when you try accessing it, in other words, if the file or the path you specified is not valid (the file and the path are not checked at compilation time, they are checked when the application is asked to retrieve the bitmap), you would receive an error:

As you can see, the exception thrown is of type EFOpenError (which stands for Exception-File-Open-Error), meaning that the information given about opening the file is incorrect somewhere. You can display our own message as follows:

//---------------------------------------------------------------------------
void __fastcall TForm1::FormDblClick(TObject *Sender)
{
	Graphics::TBitmap *BmpMercedes = new Graphics::TBitmap;

	try {
		try {
			BmpMercedes->LoadFromFile("Mercedes.bmp");
		}
		catch(EFOpenError *Error)
		{
			ShowMessage(Error->Message +
				    ".\nThe file path, its name, or its extension”
				    "may be invalid or they don't exist.");
		}
	}
	__finally
	{
		delete BmpMercedes;
	}
}
//---------------------------------------------------------------------------
 

Bitmap Loading From a Resource File

Another technique you can use to open a bitmap consists of retrieving it from a resource file. Before doing this, you must have a resource file with .res extension. You can directly create a resource file from Image Editor but once again, you would have to deal with that application’s limitations. Alternatively, you can first create a Windows resource file that has the .rc extension and create a header file that lists its resources. The header file is used to specify a constant number for each resource. For this example, the header file can be named resource.h. In the file, a constant can be defined as follows:

#define DEUXFILES 1000

After creating the header file, you can create a resource file, which is simply a text file with an extension of .rc and, in the file, each resource can be specified using the name of the constant created in the header file. A bitmap resource can be created as follows:

#include "resource.h"

DEUXFILLES BITMAP "Filles.bmp"

After creating the resource file, you must import it into your project. This is done by click Project -> Add to Project… from the main menu, selecting the rc file and clicking Open. After adding the resource file, you should compile it to produce a .res file. This makes your file ready.

Once a bitmap in a resource file is ready, to use it in your application, you can call the LoadFromResourceName() method. Its syntax is:

void __fastcall LoadFromResourceName(unsigned Instance, const AnsiString ResName);

The easiest way to do this is to create the resource file in the same directory as the project that is using it. This is because the LoadFromResourceName() method requires the instance of the executable file that contains the resource file. If it is located in the same folder, you can simply pass the instance of the current project as the Instance argument. The second parameter, ResName, is the name of the bitmap to be loaded. Normally, it should be the identifier of the bitmap as defined in the header file.

Here is an example:

//---------------------------------------------------------------------------
#include <vcl.h>
#pragma hdrstop

#include "Exercise.h"
#include "resource.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
	: TForm(Owner)
{
}
//---------------------------------------------------------------------------
void __fastcall TForm1::FormPaint(TObject *Sender)
{
	Graphics::TBitmap *BmpFilles = new Graphics::TBitmap;

	try {
		try {
		    BmpFilles->LoadFromResourceName((int)HInstance, "DEUXFILLES");
		    Canvas->Draw(0, 0, BmpFilles);
		}
		catch(EResNotFound *Error)
		{
			ShowMessage(Error->Message +
				    ".\nThe resource file was not found or its "
				    "name is incorrect.");
		}
		catch(...)
		{
			ShowMessage("The picture cannot be displayed...");
		}
	}
	__finally
	{
		delete BmpFilles;
	}
}
//---------------------------------------------------------------------------
 

Bitmap Loading From a Resource Identifier

One more alternative you have into preparing a picture to display in your application consists of using an identifier from a resource file. Since the steps are exactly the same as those used above, we will follow them in a Practical Learning session.

Practical Learning Practical Learning: Loading a Bitmap From Resource

  1. Create a new project with its default form
  2. Save the application in a new folder named Bitmaps1
  3. Save the unit as Exercise and save the project as Bitmaps1
  4. Change the form’s caption to Picture Display
  5. From the resources that accompany this book, copy the food1.bmp file and paste it in the folder of the current project
  6. On the main menu of C++ Builder, click File -> New -> Other…
  7. In the New Items dialog box, click Header File and click OK
  8. In the empty file, type
     
    #define FOODITEM 101
  9. Save the file as resource.h and make sure you include the extension. Also, make sure you save it in the folder of the current project
  10. On the Standard toolbar of C++ Builder, click the New button
  11. In the New Items dialog box, double-click the Text icon
  12. In the empty file, type:

    #include "resource.h"

    FOODITEM BITMAP "food1.bmp"
  13. To save the file, on the Standard toolbar, click the Save button
  14. Type “ExoRes.rc” to make sure the file is saved with the rc extension instead of txt:
     
  15. Click Save
  16. On the main menu, click Project -> Add to Project…
  17. In the Files of Type combo box, select Resource file (*.rc) and, in the list of files, click ExoRes.rc
     
  18. Click Open
  19. While the ExoRes.rc tab is displaying, to compile it, on the main menu, click Project -> Compile Unit
     
  20. When the compilation is complete, on the Compiling dialog box, click OK
  21. On the Object Inspector, click the Events tab and access the OnPaint event of the form
  22. Implement it as follows:
     
    //---------------------------------------------------------------------------
    #include <vcl.h>
    #pragma hdrstop
    
    #include "Exercise.h"
    #include "resource.h"
    //---------------------------------------------------------------------------
    #pragma package(smart_init)
    #pragma resource "*.dfm"
    TForm1 *Form1;
    //---------------------------------------------------------------------------
    __fastcall TForm1::TForm1(TComponent* Owner)
    	: TForm(Owner)
    {
    }
    //---------------------------------------------------------------------------
    void __fastcall TForm1::FormPaint(TObject *Sender)
    {
    	Graphics::TBitmap *BmpFood = new Graphics::TBitmap;
    
    	try {
    		try {
    			BmpFood->LoadFromResourceID((int)HInstance, FOODITEM);
    			Canvas->Draw(20, 10, BmpFood);
    		}
    		catch(EResNotFound *Problem)
    		{
    			ShowMessage(Problem->Message +
    				    ".\nThe resource file was not found "
    				    "or its name is incorrect.");
    		}
    		catch(...)
    		{
    			ShowMessage("The picture cannot be displayed...");
    		}
    	}
    	__finally
    	{
    		delete BmpFood;
    	}
    }
    //---------------------------------------------------------------------------
  23. Test the application
     
  24. Close it and return to Borland C++ Builder

Characteristics of Bitmaps

In most circumstances, in order to use a bitmap, you will need to declare a pointer to TBitmap. Because the TBitmap class has only a default constructor, after declaring the pointer, you will need to load a bitmap into it before using it. Once the variable contains a bitmap, you can use it as you see fit. If there is no bitmap stored into it and you attempt to use it, you may receive an error or an unreliable result. If you want to check first whether the variable contains a bitmap, you can check its Empty Boolean value. If the variable contains a bitmap, this property would be true. Otherwise, it would be false.

Once a bitmap has been loaded, as a visible object, it has dimensions represented by a width and a height. These are its Width and its Height properties. You can either retrieve these values or change them.

A bitmap uses a set of colors known as its palette. To get or set the characteristics of these colors, you can access the Palette property of the TBitmap variable.

When a bitmap displays, it uses all allowable colors and occupies the whole area allocated to its Width and Height values. If you want the bitmap to display only certain parts, set its Transparent property to true.

When designing a picture that would display with transparency, you should use one color to paint the areas that would not display. For example, the doughnut in the following exercise was surrounded by a white color. When it displays with the Transparent property set to true, the white area surrounding it is seen through.

So far, we have seen first how to declare a bitmap variable, second how to load it into an application. Once such a bitmap is ready, you can use it in various ways as we saw that you can display it on the form. You can also make a duplicate copy of it and store it in another variable. This can be done using the Assign() method. Its syntax is:

virtual void __fastcall Assign(Classes::TPersistent* Source);

The Source parameter is the variable that holds the bitmap you want to copy and will be assigned to the variable that is making the call.

Practical Learning Practical Learning: Using a Bitmap Properties

  1. From the resources that accompany this book, copy doughnut1.bmp and doughnut2.bmp. Then paste them in the folder of this project
  2. Change the resource.h file as follows:

    #define FOODITEM 101
    #define DOUGHNUT1 102
    #define DOUGHNUT2 103
  3. Change the ExoRes.rc file as follows:
     
    #include "resource.h"

    FOODITEM BITMAP "food1.bmp"
    DOUGHNUT1 BITMAP "doughnut1.bmp"
    DOUGHNUT2 BITMAP "doughnut2.bmp"
  4. Recompile the ExoRes.rc file to update the res file
  5. To display the new pictures, change the OnPaint event of the form as follows:
     
    //---------------------------------------------------------------------------
    void __fastcall TForm1::FormPaint(TObject *Sender)
    {
    	Graphics::TBitmap *BmpFood1 = new Graphics::TBitmap;
    	Graphics::TBitmap *BmpFood2 = new Graphics::TBitmap;
    	int width;
    
    	try {
    		try {
    			BmpFood1->LoadFromResourceID((int)HInstance, DOUGHNUT1);
    			Canvas->Draw(20, 10, BmpFood1);
    
    			width = BmpFood1->Width + 40;
    			BmpFood2->LoadFromResourceID((int)HInstance, DOUGHNUT2);
    			BmpFood2->Transparent = True;
    			Canvas->Draw(width, 10, BmpFood2);
    		}
    		catch(EResNotFound *Problem)
    		{
    		    ShowMessage(Problem->Message +
    			".\nThere was a problem completing this assignment");
    		}
    	}
    	__finally
    	{
    		delete BmpFood1;
    		delete BmpFood2;
    	}
    }
    //---------------------------------------------------------------------------
  6. Test the application
     
  7. Close it and return to Borland C++ Builder
  8. Save All

Pattern Brushes

A pattern brush is one that uses a bitmap instead of a plain color like the solid brush. Therefore, to use a pattern brush, you must first create a bitmap. There are two main options to do this. You can first load a bitmap from a file as we have done so far. Once the bitmap is ready, assign its pointer to the Bitmap property of the Brush member variable of the TCanvas class you are using.

Alternatively, to create a pattern brush, you can declare and initialize an array of BYTE values that describe the bitmap.

Practical Learning Practical Learning: Using a Pattern Brush

  1. Create a new project with its default form
  2. Save it in a new folder named PatternBrush1
  3. Save the unit as Exercise and the project PatBrush
  4. Using Image Editor, create a 38 x38 pixels bitmap and design it as follows:
     
  5. Save it in the folder of the current project as Diamond
  6. Create a 32x32 pixels icon and design it as follows:
     
  7. Associate a 16x16 pixels icon to it and design it as follows:
     
  8. Save the icon are PatBrush in the folder of the current project
  9. Using the Project -> Options menu and the Load Icon button from the Application tab, select the new icon
  10. Using the Events tab of the Object Inspector, access the OnPaint event of the form and implement it as follows:
     
    //---------------------------------------------------------------------------
    void __fastcall TForm1::FormPaint(TObject *Sender)
    {
    	Graphics::TBitmap *BmpDiamond = new Graphics::TBitmap;
    
    	BmpDiamond->LoadFromFile("Diamond.bmp");
    	Canvas->Pen->Color = clBlue;
    	Canvas->Brush->Bitmap = BmpDiamond;
    	Canvas->Rectangle(0, 0, 346, 190);
    }
    //---------------------------------------------------------------------------
  11. Test the application
     
  12. Close it and return to Borland C++ Builder
  13. Save All

Win32 Support for Bitmaps

 

Introduction

The primary means of using a bitmap in your application is obviously through the TBitmap class with its properties and methods. If the VCL does not natively provide the bitmap functionality you are using for, you can use one of the Win32 functions. The Win32 library supports bitmaps through various functions. Most of these functions return a handle to BITMAP, implemented as HBITMAP. To use the return value of one of these, the TBitmap class provides a Handle member variable particularly easy to use, just all Handle member variables provided by the TWinControl class to its children. Therefore, anything you would have done on the HBITMAP handle, to use it in your application, simply assign its variable to the TCanvas::Handle and it is made ready.

A bitmap, like any other GDI object, must be created first, either as a resource file or by definition. Once it exists, before using it, it must be selected into a device context. Fortunately, the device context is already largely implemented in VCL objects through the TCanvas class that is made a member variable of all classes that need a device context.

Bitmap Creation

The most basic bitmap is created from an array of constant values that describe the bitmap. This type is created using the CreateBitmap() function. Its syntax is:

HBITMAP CreateBitmap(int nWidth,
                     int nHeight,
                     UINT cPlanes,
                     UINT cBitsPerPel,
                     CONST VOID *lpvBits);

The nWidth and nHeight parameters specify the dimensions of the bitmap, in pixels. The cPlanes parameter holds the number of color planes used by the device. The cBitsPerPel parameter is an array of color values.

This CreateBitmap() function returns a handle to the BITMAP structure. You can assign that value to the Handle member variable of the TBitmap class.

Here is an example:

//---------------------------------------------------------------------------
void __fastcall TForm1::FormPaint(TObject *Sender)
{
	HBITMAP HBmp;
	WORD wBits[] = { 0x00, 0x22, 0x44, 0x88, 0x00, 0x22, 0x44, 0x88,
			 0x22, 0x44, 0x88, 0x00, 0x22, 0x44, 0x88, 0x00,
			 0x44, 0x88, 0x00, 0x22, 0x44, 0x88, 0x00, 0x22,
			 0x88, 0x00, 0x22, 0x44, 0x88, 0x00, 0x22, 0x44 };

	HBmp = CreateBitmap(32, 32, 1, 1, wBits);
	HBRUSH hBrush = CreatePatternBrush(HBmp);

	Canvas->Brush->Handle = hBrush;
	Canvas->Rectangle(20, 20, 400, 400);
}
//---------------------------------------------------------------------------

Image Lists

 

Overview

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 Tool 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;
}
//---------------------------------------------------------------------------
Previous Copyright © 2005 Yevol Next