Kürzlich stieß ich bei der Arbeit an einem Projekt auf die Situation, eine Reihe von Bildern in einer Bildliste (TImageList) in einer bestimmten Datei oder einem Binärstream zu speichern, damit sie bei Bedarf dynamisch wiederhergestellt werden können. Deshalb habe ich in der Delphi-Hilfe nach den Eigenschaften und Methoden gesucht, die sich auf die Klasse TImageList beziehen. Leider stellt Delphi die Methoden SaveToFile und SaveToStream in TImageList nicht zur Verfügung. Daher müssen andere Methoden übernommen werden, um die zu erweitern Funktionen von TImageList, um den tatsächlichen Projektanforderungen gerecht zu werden. |
Lösung |
Methode eins: |
Verwenden Sie die API-Funktionen ImageList_Write und ImageList_Read. Beide müssen einen Parameter vom Typ IStream angeben. Die Funktion des ersteren besteht darin, die Bildliste des angegebenen Handles in einem Binärstrom vom Typ IStream zu speichern . und gibt ein Handle für diese Bildliste zurück. IStream ist ein OLE-Objekt und seine Deklaration in Delphi lautet TStreamAdapter = class(TInterfacedObject, IStream), was bedeutet, dass TStreamAdapter ein von TInterfacedObject geerbtes Objekt ist, das die IStream-Schnittstelle manipuliert. Über das TStreamAdapter-Objekt kann die Manipulation des ISTream-Schnittstellenobjekts durch das Delphi-interne TStream-Objekt realisiert werden. |
Methode zwei: |
Erben Sie eine Unterklasse TImageListEx von TImageList und implementieren Sie die benutzerdefinierten Methoden SaveToFileEx und SaveToStreamEx. Standardmäßig bestehen die in TImageList gespeicherten Bilder aus gewöhnlichen Bildern und ihren Maskenbildern, daher muss GetImages(Index: Integer; Image, Mask: bereitgestellt vom PRotected-Teil seiner Basisklasse TCustomImageList) aufgerufen werden. TBitmap)-Methode, um die Bitmap mit der angegebenen Indexnummer in der Bildliste und ihrer Masken-Bitmap abzurufen und sie dann in einer benutzerdefinierten Datei bzw. einem Binärstream zu speichern. Darüber hinaus müssen die Methoden LoadFromFileEx und LoadFromStreamEx bereitgestellt werden, um die zu erhalten Bitmap aus der benutzerdefinierten Datei oder dem Binärstream. Bildsammlung aus Stream wiederherstellen. |
Umsetzungsschritte |
Das benutzerdefinierte TImageListEx-Steuerelement kapselt die beiden oben genannten Methoden im öffentlichen Teil. |
Der Quellcode der TImageListEx-Klasse lautet wie folgt: |
Einheit ImageListEx; |
Schnittstelle |
verwendet Windows, SysUtils, Klassen, Grafiken, Steuerelemente, Commctrl, ImgList, Consts; |
Typ |
TImageListEx = class(TImageList) |
öffentlich |
procedure LoadFromFile(const FileName: string);//API-Methode zum Speichern implementieren |
Prozedur LoadFromStream(Stream: TStream); |
procedure SaveToFile(const FileName: string); |
procedure SaveToStream(Stream: TStream); |
procedure LoadFromFileEx(const FileName: string);//Benutzerdefinierte Speichermethode erreichen |
procedure LoadFromStreamEx(Stream: TStream); |
procedure SaveToFileEx(const FileName: string); |
procedure SaveToStreamEx(Stream: TStream); |
Ende; |
Verfahren Registrieren; |
Durchführung |
Verfahren Registrieren; |
beginnen |
RegisterComponents('ImageListEx', [TImageListEx]); |
Ende; |
{TImageListEx} |
procedure TImageListEx.LoadFromFile(const FileName: string); |
var |
Stream: TStream; |
beginnen |
Stream := TFileStream.Create(FileName, fmOpenRead); |
versuchen |
LoadFromStream(Stream); |
Endlich |
Stream.Free; |
Ende; |
Ende; |
procedure TImageListEx.LoadFromFileEx(const FileName: string); |
var |
Stream: TStream; |
beginnen |
Stream := TFileStream.Create(FileName, fmOpenRead); |
versuchen |
LoadFromStreamEx(Stream); |
Endlich |
Stream.Free; |
Ende; |
Ende; |
procedure TImageListEx.LoadFromStream(Stream: TStream); |
var |
SA: TStreamAdapter; |
beginnen |
SA := TStreamAdapter.Create(Stream); |
versuchen |
Handle := ImageList_Read(SA); // Richten Sie das Handle der aktuellen Bildliste auf das aus dem Binärstream erhaltene Handle |
wenn Handle = 0 dann |
raise EReadError.CreateRes(@SImageReadFail); |
Endlich |
SA.Free; |
Ende; |
Ende; |
procedure TImageListEx.LoadFromStreamEx(Stream: TStream); |
var |
Breite, Höhe: Ganzzahl; |
Bitmap, Maske: TBitmap; |
BinStream: TMemoryStream; |
procedure LoadImageFromStream(Image: TBitmap); |
var |
Anzahl: DWord; |
beginnen |
Image.Assign(nil); |
Stream.ReadBuffer(Count, SizeOf(Count));//Lesen Sie zuerst die Größe der Bitmap |
BinStream.Clear; |
BinStream.CopyFrom(Stream, Count);//Lesen Sie dann die Bitmap |
BinStream.Position := 0; //Stream-Zeiger zurückgesetzt |
Image.LoadFromStream(BinStream); |
Ende; |
beginnen |
Stream.ReadBuffer(Height, SizeOf(Height)); |
Stream.ReadBuffer(Width, SizeOf(Width)); |
Self.Height := Höhe; |
Self.Width := Breite; // Stellen Sie die ursprüngliche Höhe und Breite der Bildliste wieder her |
Bitmap := TBitmap.Create; |
Maske := TBitmap.Create; |
BinStream := TMemoryStream.Create; |
versuchen |
while Stream.Position <> Stream.Size do |
beginnen |
LoadImageFromStream(Bitmap);//Bitmap aus Binärstream lesen |
LoadImageFromStream(Mask);//Lesen Sie die Maskenbitmap aus dem Binärstream |
Add(Bitmap, Mask);// Füge die Bitmap und ihre Masken-Bitmap zur Bildliste hinzu |
Ende; |
Endlich |
Bitmap.Free; |
Mask.Free; |
BinStream.Free; |
Ende; |
Ende; |
procedure TImageListEx.SaveToFile(const FileName: string); |
var |
Stream: TStream; |
beginnen |
Stream := TFileStream.Create(FileName, fmCreate); |
versuchen |
SaveToStream(Stream); |
Endlich |
Stream.Free; |
Ende; |
Ende; |
procedure TImageListEx.SaveToFileEx(const FileName: string); |
var |
Stream: TStream; |
beginnen |
Stream := TFileStream.Create(FileName, fmCreate); |
versuchen |
SaveToStreamEx(Stream); |
Endlich |
Stream.Free; |
Ende; |
Ende; |
procedure TImageListEx.SaveToStream(Stream: TStream); |
var |
SA: TStreamAdapter; |
beginnen |
SA := TStreamAdapter.Create(Stream); |
versuchen |
wenn nicht ImageList_Write(Handle, SA) then//Speichern Sie die aktuelle Bildliste im Binärstream |
raise EWriteError.CreateRes(@SImageWriteFail); |
Endlich |
SA.Frei; |
Ende; |
Ende; |
procedure TImageListEx.SaveToStreamEx(Stream: TStream); |
var |
I: Ganzzahl; |
Breite, Höhe: Ganzzahl; |
Bitmap, Maske: TBitmap; |
BinStream: TMemoryStream; |
procedure SetImage(Image: TBitmap; IsMask: Boolean); |
beginnen |
Image.Assign(nil);//Das zuletzt gespeicherte Bild löschen, um Bildüberlappungen zu vermeiden |
mit Bild tun |
beginnen |
if IsMask then MonoChrome := True;//Die Maskenbitmap muss Monochrom verwenden |
Höhe := Self.Height; |
Breite := Self.Width; |
Ende; |
Ende; |
procedure SaveImageToStream(Image: TBitmap); |
var |
Anzahl: DWORD; |
beginnen |
BinStream.Clear; |
Image.SaveToStream(BinStream); |
Count := BinStream.Size; |
Stream.WriteBuffer(Count, SizeOf(Count));//Speichern Sie zuerst die Größe der Bitmap |
Stream.CopyFrom(BinStream, 0);//Dann speichern Sie die Bitmap |
Ende; |
beginnen |
Höhe := Self.Height; |
Breite := Self.Width; |
Stream.WriteBuffer(Height, SizeOf(Height));//Speichern Sie die Höhe der Originalbildliste |
Stream.WriteBuffer(Width, SizeOf(Width));//Speichern Sie die Breite der Originalbildliste |
Bitmap := TBitmap.Create; |
Maske := TBitmap.Create; |
BinStream := TMemoryStream.Create; |
versuchen |
for I := 0 to Count - 1 do//Speichere das Bild in der Bildliste |
beginnen |
SetImage(Bitmap, False); |
SetImage(Maske, True); |
GetImages(I, Bitmap, Mask);//Holen Sie sich die Bitmap mit der angegebenen Indexnummer und ihre Masken-Bitmap |
SaveImageToStream(Bitmap);//Bitmap im Binärstream speichern |
SaveImageToStream(Mask);//Speichern Sie die Maskenbitmap im Binärstream |
Ende; |
Endlich |
Bitmap.Free; |
Mask.Free; |
BinStream.Free; |
Ende; |
Ende; |
Ende. |
Im Folgenden wird die Verwendung in Delphi veranschaulicht: |
Erstellen Sie zunächst ein neues Projekt in Delphi und platzieren Sie dann ein ImageListEx-Steuerelement, ein TreeView-Steuerelement und vier Button-Steuerelemente auf Form1. Verknüpfen Sie die Images-Eigenschaft des TreeView-Steuerelements mit ImageListEx, fügen Sie eine beliebige Anzahl von Bildern zu ImageListEx hinzu und fügen Sie eine entsprechende Anzahl von Elementen zu TreeView hinzu. Die ImageIndex-Eigenschaften der Elemente entsprechen den Indexnummern der Bilder in ImageListEx. Jetzt kann vor jedem Element in TreeView das entsprechende Symbol angezeigt werden. |
Schreiben Sie abschließend in das OnClick-Ereignis von Button1: |
ImageListEx1.SaveToFile('C:CJ.dat'); |
ImageListEx1.SaveToFileEx('C:CJEx.dat'); |
Schreiben Sie im OnClick-Ereignis von Button2: ImageListEx1.Clear; |
Schreiben Sie in das OnClick-Ereignis von Button3: ImageListEx1.LoadFromFile('C:CJ.dat'); |
Schreiben Sie in das OnClick-Ereignis von Button4: ImageListEx1.LoadFromFileEx('C:CJEx.dat'); |
Führen Sie das Programm aus, klicken Sie zuerst auf Button1, dann auf Button2 und schließlich auf Button3 oder Button4. Sie können sehen, dass das Programm die Bilder in der Bildliste in der angegebenen Datei speichern und sie aus der angegebenen Datei korrekt wiederherstellen und anzeigen kann. . |
Abschluss |
Der in diesem Artikel vorgestellte Inhalt wurde verwendet, um die Situation zu lösen, auf die ich in tatsächlichen Projekten gestoßen bin. Ich hoffe auch, dass Programmierer, die ebenfalls auf dieses Problem stoßen, die Antwort daraus finden können. Der obige Code hat das Debuggen bestanden und wurde in Delphi5.0 und Windows2000 Server ausgeführt. |