Originally published in Computer World Daily:
http://www.ccw.com.cn/htm/app/aprog/01_6_5_2.asp
Save Image List in Delphi Cai Jian 01-6-5 02:07:11
Recently, when you do a project, you will have a series of images in the TimageList to be saved to the specified file or binary stream in order to perform dynamic recovery when needed. So find the TimageList class related properties, methods, unfortunately, unfortunately, in TimageList, in TimageList, so that Delphi is not provided in TimageList, so other methods must be taken to expand TimageList's feature to meet The actual project needs.
Solution
method one:
Use the API function imagelist_write and imagelist_read. Both need to specify a parameter of type ISTREAM. The former's role is to save the image list of the specified handle to the binary stream of ISTREAM; the latter is a list of originally saved images from the type ISTREAM. List And return the handle pointing to this image list. IStream is an OLE object that declares in delphi is TSTREAMADAPTER = Class (TinterFaceDObject, ISTREAM), which means that TSTREAMADAPTER is an object that inherits the manipulation IStream interface inherited from TinterFaceDObject. The TSTREAMADAPTER object can realize the manipulation of the Delphi internal TSTREAM object to the ISTREAM interface object.
Method Two:
Inheriting a subclass TIMAGELISTEX from TIMAGELIST to implement custom SaveTOFILEX and SaveTreamTreamEx methods. By default, the image saved in TimageList is combined by a normal image and its mask image, so it is necessary to call the GetImages (INDEX: Integer; Image, Mask: Tbitmap) method provided by the Protected TcustomImageList's Protected PROTECTED section to get The bitmap of the index number and its mask bitmap are specified in the image list, which are saved to a custom file or binary stream, and the LoadFromFireEx and LoadFromstreamStreamEx methods are required to recover image collections from custom files or binary streams.
Implementation steps
Customized TimageListex controls have implemented packages of the above two methods in the Public section.
The TimageListex Class source code is as follows:
Unit imagelistex;
Interface
Uses Windows, Sysutils, Classes, Graphics, Controls, CommCtrl, Imglist, Consts
Type
TimageListex = Class (timagelist)
public
Procedure loadFromfile (const filename: string); // Realize API mode Save
Procedure LoadFromstream (Stream: TStream);
Procedure Savetofile (const filename: string);
Procedure Savetostream (Stream: TStream);
Procedure LoadFromFileEx (const filename: string); // Realize custom mode Save
Procedure LoadFromstreamStreamEx (Stream: TSTream);
Procedure SavetofileEx (const filename: string);
Procedure SavetostreamEx (Stream: TStream);
END;
Procedure register; importation
PROCEDURE register;
Begin
RegisterComponents ('ImageListex', [TimageListex]);
END;
{TIMAGELISTEX}
Procedure Timagelistex.LoadFromfile (const filename: string);
VAR
Stream: TSTREAM;
Begin
Stream: = TFileStream.create (filename, fmopenread);
Try
LoadFromstream (stream);
Finally
Stream.free;
END;
END;
Procedure Timagelistex.LoadFromfileEx (const filename: string);
VAR
Stream: TSTREAM;
Begin
Stream: = TFileStream.create (filename, fmopenread);
Try
LoadFromstreamEx (stream);
Finally
Stream.free;
END;
END;
Procedure Timagelistex.LoadFromstream (Stream: TSTREAM);
VAR
SA: TSTREAMADAPTER;
Begin
SA: = TSTREAMADAPTER.CREATE (Stream);
Try
Handle: = imagelist_read (sa); // Point the handle of the current image list points to the handle obtained from the binary stream
IF Handle = 0 THEN
Raise EREADERROR.CREATERES (@simagereadfail);
Finally
Sa.free;
END;
END;
Procedure Timagelistex.LoadFromstreamEx (Stream: TStream);
VAR
Width, Height: Integer;
Bitmap, Mask: Tbitmap
Binstream: TMemoryStream;
Procedure loadImagefromstream (image: tbitmap);
VAR
Count: DWORD;
Begin
Image.Assign (nil);
Stream.readbuffer (count, sizeof (count); // first read the size of the bitmap
Binstream.clear;
Binstream.copyfrom (stream, count); / / Next reading bit map
Binstream.position: = 0; // Flow pointer reset
Image.LoadFromstream (Binstream);
END;
Begin
Stream.readbuffer (Height, Sizeof (HEIGHT));
Stream.readbuffer (Width, Sizeof (Width));
Self.height: = Height;
Self.width: = width; // Restore the image list original height, width
Bitmap: = Tbitmap.create;
Mask: = Tbitmap.create;
Binstream: = TMEMORYSTREAM.CREATE;
Try
While Stream.Position <> stream.size do
Begin
LoadImageFromstream (Bitmap); // Read the chart from the binary stream
LoadImageFromstream (MASK); // Read the mask bitmap from the binary stream
Add (Bitmap, Mask); // combines bitmaps and its mask bitmaps to the image list;
Finally
Bitmap.free;
Mask.free;
Binstream.free;
END;
END;
Procedure Timagelistex.savetofile (const filename: string);
VAR
Stream: TSTREAM;
Begin
Stream: = TfileStream.create (filename, fmcreate);
Try
SaveTostream (stream);
Finally
Stream.free;
END;
END;
Procedure Timagelistex.savetofileEx (Const filename: string);
VAR
Stream: TSTREAM;
Begin
Stream: = TfileStream.create (filename, fmcreate);
Try
SavetostreamEx (stream);
Finally
Stream.free;
END;
END;
Procedure Timagelistex.saveTostream (Stream: TStream);
VAR
SA: TSTREAMADAPTER;
Begin
SA: = TSTREAMADAPTER.CREATE (Stream);
Try
If not imagelist_write (handle, sa) then // save the current image list to the binary stream
Raise EwriteError.createres (@SimageWriteFail);
Finally
Sa.free;
END;
END;
Procedure Timagelistex.saveTroupTreamEx (Stream: TStream);
VAR
I: integer;
Width, Height: Integer;
Bitmap, Mask: Tbitmap
Binstream: TMemoryStream;
Procedure setImage (image: tbitmap; ismask: boolean);
Begin
Image.Assign (NIL); / / Clear the previously saved image to avoid image overlapping
WITH Image Do
Begin
If ismask the monochrome: = true; // Mask Bitmap must use monochrome
Height: = Self.height;
Width: = Self.width;
END;
END;
Procedure SaveImageTroupTream (Image: Tbitmap);
VAR
Count: DWORD;
Begin
Binstream.clear;
Image.savetostream (binstream);
Count: = binstream.size;
Stream.writebuffer (count, sizeof (count); // Save the size of the bitmap first
Stream.copyFrom (binstream, 0); / / then save bitmap
END;
Begin
Height: = Self.height;
Width: = Self.width;
Stream.WriteBuffer (HEIGHT, SIZEOF (HEIGHT)); / / Save the height of the original image list
Stream.WriteBuffer (Width, SizeOf (Width)); / / Save the width of the original image list
Bitmap: = Tbitmap.create;
Mask: = Tbitmap.create;
Binstream: = TMEMORYSTREAM.CREATE;
Try
For i: = 0 to count - 1 do // 一 保 保 保 图像 图像 图像 图像 图像
SetImage (Bitmap, False);
SetImage (Mask, True);
GetImages (I, Bitmap, Mask); // Get the bitmap of the specified index number and its mask bitmap
SaveImageTroupTream (Bitmap); // Save bitmap to the binary stream
SaveImageTroupTream (MASK); // Save Mask Bit map to the binary stream
END;
Finally
Bitmap.free;
Mask.free;
Binstream.free;
END;
END;
End.
The method of use in Delphi is shown below:
First, create a project in Delphi, then place an ImageLisTex control on Form1, a TreeView control, and four Button controls. Associate the image of the TreeView control with ImageListex, any number of images in ImageListex, add a corresponding number of items in the TreeView, the IMAGEX attribute of the item corresponds to the index number of the image in ImageListex. Now you have been able to display the appropriate icons before each project in TreeView.
Finally, write on the Button1 on the onclick event:
Imagelistex1.savetofile ('c: /cj.dat');
ImageListex1.savetofileex ('c: /cjex.dat');
Write on the Button2 onclick event: imagelistex1.clear;
Write on the onclick event of Button3: imagelistex1.loadfromfile ('c: /cj.dat');
Write on the onclick event of Button4: imagelistex1.loadfromfileex ('c: /cjex.dat');
Run the program, first click Button1, then click Button2, and then click Button3 or Button4, you can see that the program can save the image in the image list to the specified file, you can correctly restore and display it from the specified file. .
Conclude
The content introduced in this article has been used to solve the situation I have encountered in the actual project, and I hope that the programmer who will also encounter this problem can find the answer. The above code is tested in Delphi5.0, Windows2000 Server.