List of Bitmaps the Use of Resources and a Control Canvas

The World program works, but it is very slow, for a couple of reasons. First of all, at each timer interval, it needs to read a file from the disk, and although a disk cache can make this faster, it is certainly not the most efficient solution. Besides reading the file from disk, the program has to create and destroy Windows bitmap objects, and this takes some time. The second problem depends on how the image is updated: When you change the button's bitmap, the component is completely erased and repainted. This causes some flickering, as you can see by running the program.

To solve the first problem (and to show you a different approach to handling bitmaps), I've created a second version of the example, World2. Here I've added a TObjectList Delphi 5 container, storing a list of bitmaps, to the program's form. The form has also some more fields:

type

TWorldForm = class(TForm)

private

Count, YPos, XPos: Integer;

BitmapsList: TObjectList;

ControlCanvas: TControlCanvas;

end;

All the bitmaps are loaded when the program starts and destroyed when it terminates. At each timer interval, the program shows one of the list's bitmaps in the bitmap button. By using a list, we avoid loading a file each time we need to display a bitmap, but we still need to have all the files with the images in the directory with the executable file. A solution to this problem is to move the bitmaps from independent files to the application's resource file. This is easier to do than to explain.

To use the resources instead of the bitmap files, we need to first create this file. The best approach is to write a resource script (an RC file), listing the names of the bitmap files and of the corresponding resources. Open a new text file (in any editor) and write the following code:

W1

BITMAP

"W1.

BMP

W2

BITMAP

"W2.

BMP

W3

BITMAP

"W3.

BMP

//

... and

so on

Once you have prepared this RC file (I've named it WorldBmp.RC), you can compile it into a RES file using the resource compiler included and the BRCC32 command-line application you can find in the BIN directory of Delphi, and then include it in the project by adding the {$R WORLDBMP.RES} directive in the project source code file or in one of the units.

In Delphi 5, however, you can use a simpler approach. You can take the RC file and simply add it to the project using the Project Manager Add command or simply dragging the file to the project. Delphi 5 will automatically activate the resource compiler, and it will then bind the resource file into the executable file. These operations are controlled by an extended resource inclusion directive added to the project source code:

Once we have properly defined the resources of the application, we need to load the bitmaps from the resources. For a TBitmap object we can use the Load-FromResourceName method, if the resource has a string identifier, or the LoadFrom-ResourcelD method, if it has a numeric identifier. The first parameter of both methods is a handle to the application, known as HInstance, available in Delphi as a global variable.

Delphi defines a second global variable, Mainlnstance, which refers to the HInstance of the main executable file. Unless you are inside a DLL, you can use one or the other interchangeably.

This is the code of the FormCreate method:

procedure TWorldForm.FormCreate(Sender: TObject); var

I: Integer; Bmp: TBitmap; begin

// load the bitmaps and add them to the list BitmapsList := TList.Create; for I := 1 to 16 do begin

Bmp := TBitmap.Create; Bmp.LoadFromResourceName (HInstance,

'W' + IntToStr (I)); BitmapsList.Add (Bmp); end; end;

NOTE

As an alternative, we could have used the ImageList component, but for this example I decided to use a low-level approach to show you all the details involved.

One problem remains to be solved: obtaining a smooth transition from one image of the world to the following one. The program should paint the bitmaps in a canvas using the Draw method. Unfortunately, the bitmap button's canvas is not directly available (and not event protected), so I decided to use a TControl-Canvas (usually the internal canvas of a control, but one you can also associate to externally) To use it to paint over a button, we can assign the button to the control canvas in the FormCreate method:

ControlCanvas := TControlCanvas.Create;

ControlCanvas.Control := WorldButton;

YPos := (WorldButton.Height - Bmp.Height) div 2;

XPos := WorldButton.Margin;

The horizontal position of the button where the image is located (and where we should paint) depends on the Margin of the icon of the bitmap button and on the height of the bitmap. Once the control canvas is properly set, the TimerlTimer method simply paints over it—and over the button:

procedure TWorldForm.Timer1Timer(Sender: TObject); begin

Labell.Caption := Format ('Displaying image %d', [Count]);

// draw the current bitmap in the control canvas

  1. Draw (XPos, YPos,
  2. Items[Count-1] as TBitmap);

end;

The last problem is to move the position of the image when the left mouse button is pressed or released over it (that is, in the OnMouseDown and OnMouseUp events of the button). Besides moving the image by few pixels, we should update the glyph of the bitmap, because Delphi will automatically display it while redrawing the button. Otherwise, a user would see the initial image until the timer interval elapsed and the component fired the OnTimer event. (That might take a while if you've stopped it!) Here is the code of the first of the two methods:

procedure TWorldForm.WorldButtonMouseDown(Sender: TObject;

Button: TMouseButton; Shift: TShiftState; X, Y: Integer); begin if Button = mbLeft then begin

// paint the current image over the button WorldButton.Glyph.Assign (

BitmapsList.Items[Count-1] as TBitmap); Inc (YPos, 2); Inc (XPos, 2); end; end;

Project Management Made Easy

Project Management Made Easy

What you need to know about… Project Management Made Easy! Project management consists of more than just a large building project and can encompass small projects as well. No matter what the size of your project, you need to have some sort of project management. How you manage your project has everything to do with its outcome.

Get My Free Ebook


Post a comment