Récemment, alors que je travaillais sur un projet, j'ai rencontré la situation de sauvegarder une série d'images dans une liste d'images (TImageList) dans un fichier ou un flux binaire spécifié afin qu'elles puissent être restaurées dynamiquement en cas de besoin. J'ai donc recherché les propriétés et méthodes liées à la classe TImageList dans l'aide de Delphi. Malheureusement, Delphi n'a pas fourni les méthodes SaveToFile et SaveToStream dans TImageList. Par conséquent, compte tenu des limitations actuelles de TImageList, d'autres méthodes doivent être adoptées pour étendre la classe. fonctions de TImageList pour répondre aux besoins réels du projet. |
Solution |
Première méthode : |
Utilisez les fonctions API ImageList_Write et ImageList_Read. Les deux doivent spécifier un paramètre de type IStream. La fonction du premier est de sauvegarder la liste d'images du handle spécifié dans un flux binaire de type IStream ; le second est de lire la liste d'images initialement enregistrée à partir du flux binaire de type IStream ; . et renvoie un handle vers cette liste d'images. IStream est un objet OLE et sa déclaration dans Delphi est TStreamAdapter = class(TInterfacedObject, IStream), ce qui signifie que TStreamAdapter est un objet hérité de TInterfacedObject qui manipule l'interface IStream. Grâce à l'objet TStreamAdapter, la manipulation de l'objet d'interface ISTream par l'objet TStream interne de Delphi peut être réalisée. |
Deuxième méthode : |
Héritez d'une sous-classe TImageListEx de TImageList et implémentez les méthodes personnalisées SaveToFileEx et SaveToStreamEx. Par défaut, les images enregistrées dans TImageList sont composées d'images ordinaires et de leurs images de masque, donc le GetImages(Index: Integer; Image, Mask: fourni par la partie PRotected de sa classe de base TCustomImageList doit être appelé) TBitmap) pour obtenir le bitmap avec le numéro d'index spécifié dans la liste d'images et son bitmap de masque, puis les enregistrer respectivement dans un fichier personnalisé ou un flux binaire. De plus, il est nécessaire de fournir les méthodes LoadFromFileEx et LoadFromStreamEx pour obtenir le. bitmap à partir du fichier personnalisé ou du flux binaire. Restaurez la collection d’images à partir du flux. |
Étapes de mise en œuvre |
Le contrôle TImageListEx personnalisé encapsule les deux méthodes ci-dessus dans la partie Public. |
Le code source de la classe TImageListEx est le suivant : |
unité ImageListEx ; |
interface |
utilise Windows, SysUtils, Classes, Graphiques, Contrôles, Commctrl, ImgList, Consts ; |
taper |
TImageListEx = classe (TImageList) |
publique |
procédure LoadFromFile(const FileName: string);//Implémenter la méthode API pour enregistrer |
procédure LoadFromStream(Stream : TStream); |
procédure SaveToFile (const FileName: string); |
procédure SaveToStream(Stream : TStream); |
procédure LoadFromFileEx(const FileName: string);//Obtenir une méthode de sauvegarde personnalisée |
procédure LoadFromStreamEx(Stream : TStream); |
procédure SaveToFileEx(const FileName: string); |
procédure SaveToStreamEx(Stream : TStream); |
fin; |
registre de procédure ; |
mise en œuvre |
registre de procédure ; |
commencer |
RegisterComponents('ImageListEx', [TImageListEx]); |
fin; |
{TImageListEx} |
procédure TImageListEx.LoadFromFile(const FileName: string); |
var |
Flux : TStream ; |
commencer |
Stream := TFileStream.Create(FileName, fmOpenRead); |
essayer |
LoadFromStream(Flux); |
enfin |
Stream.Gratuit ; |
fin; |
fin; |
procédure TImageListEx.LoadFromFileEx(const FileName: string); |
var |
Flux : TStream ; |
commencer |
Stream := TFileStream.Create(FileName, fmOpenRead); |
essayer |
LoadFromStreamEx(Flux); |
enfin |
Stream.Gratuit ; |
fin; |
fin; |
procédure TImageListEx.LoadFromStream(Stream : TStream); |
var |
SA : TStreamAdapter ; |
commencer |
SA := TStreamAdapter.Create(Stream); |
essayer |
Handle := ImageList_Read(SA); //Pointez le handle de la liste d'images actuelle vers le handle obtenu à partir du flux binaire |
si Handle = 0 alors |
augmenter EReadError.CreateRes (@SImageReadFail); |
enfin |
SA.Gratuit ; |
fin; |
fin; |
procédure TImageListEx.LoadFromStreamEx(Stream : TStream); |
var |
Largeur, hauteur : nombre entier ; |
Bitmap, masque : TBitmap ; |
BinStream : TMemoryStream ; |
procédure LoadImageFromStream(Image : TBitmap); |
var |
Compte : DWord ; |
commencer |
Image.Assign(nil); |
Stream.ReadBuffer(Count, SizeOf(Count));//Première lecture de la taille du bitmap |
BinStream.Clear; |
BinStream.CopyFrom(Stream, Count);//Puis lire le bitmap |
BinStream.Position := 0; //Réinitialisation du pointeur de flux |
Image.LoadFromStream(BinStream); |
fin; |
commencer |
Stream.ReadBuffer(Hauteur, SizeOf(Hauteur)); |
Stream.ReadBuffer(Largeur, SizeOf(Largeur)); |
Self.Height := Hauteur; |
Self.Width := Largeur;//Restaurer la hauteur et la largeur d'origine de la liste d'images |
Bitmap := TBitmap.Create; |
Masque := TBitmap.Create; |
BinStream := TMemoryStream.Create; |
essayer |
tandis que Stream.Position <> Stream.Size fait |
commencer |
LoadImageFromStream(Bitmap);//Lire le bitmap à partir du flux binaire |
LoadImageFromStream(Mask);//Lire le bitmap du masque à partir du flux binaire |
Add(Bitmap, Mask);//Ajouter le bitmap et son bitmap de masque à la liste d'images |
fin; |
enfin |
Bitmap.Gratuit ; |
Masque.Gratuit ; |
BinStream.Free ; |
fin; |
fin; |
procédure TImageListEx.SaveToFile(const FileName: string); |
var |
Flux : TStream ; |
commencer |
Stream := TFileStream.Create(FileName, fmCreate); |
essayer |
SaveToStream(Flux); |
enfin |
Stream.Gratuit ; |
fin; |
fin; |
procédure TImageListEx.SaveToFileEx(const FileName: string); |
var |
Flux : TStream ; |
commencer |
Stream := TFileStream.Create(FileName, fmCreate); |
essayer |
SaveToStreamEx(Flux); |
enfin |
Stream.Gratuit ; |
fin; |
fin; |
procédure TImageListEx.SaveToStream(Stream : TStream); |
var |
SA : TStreamAdapter ; |
commencer |
SA := TStreamAdapter.Create(Stream); |
essayer |
sinon ImageList_Write (Handle, SA) alors // Enregistre la liste d'images actuelle dans le flux binaire |
augmenter EWriteError.CreateRes (@SImageWriteFail); |
enfin |
SA.Gratuit ; |
fin; |
fin; |
procédure TImageListEx.SaveToStreamEx(Stream : TStream); |
var |
I : Entier ; |
Largeur, hauteur : nombre entier ; |
Bitmap, masque : TBitmap ; |
BinStream : TMemoryStream ; |
procédure SetImage(Image : TBitmap ; IsMask : Boolean) ; |
commencer |
Image.Assign(nil);//Effacer la dernière image enregistrée pour éviter le chevauchement des images |
avec Image faire |
commencer |
si IsMask alors MonoChrome := True ;//Le bitmap du masque doit utiliser du monochrome |
Hauteur := Soi.Hauteur; |
Largeur := Self.Width; |
fin; |
fin; |
procédure SaveImageToStream(Image: TBitmap); |
var |
Compte : DWORD ; |
commencer |
BinStream.Clear; |
Image.SaveToStream(BinStream); |
Compte := BinStream.Size ; |
Stream.WriteBuffer(Count, SizeOf(Count));//Enregistrez d'abord la taille du bitmap |
Stream.CopyFrom(BinStream, 0);//Puis enregistrez le bitmap |
fin; |
commencer |
Hauteur := Soi.Hauteur; |
Largeur := Self.Width; |
Stream.WriteBuffer(Height, SizeOf(Height));//Enregistrer la hauteur de la liste d'images d'origine |
Stream.WriteBuffer(Width, SizeOf(Width));//Enregistrer la largeur de la liste d'images d'origine |
Bitmap := TBitmap.Create; |
Masque := TBitmap.Create; |
BinStream := TMemoryStream.Create; |
essayer |
pour I := 0 à Count - 1 do//Enregistrer l'image dans la liste des images |
commencer |
SetImage(Bitmap, Faux); |
SetImage(Masque, Vrai); |
GetImages(I, Bitmap, Mask);//Obtenir le bitmap avec le numéro d'index spécifié et son bitmap de masque |
SaveImageToStream(Bitmap);//Enregistrer le bitmap dans un flux binaire |
SaveImageToStream(Mask);//Enregistrer le bitmap du masque dans le flux binaire |
fin; |
enfin |
Bitmap.Gratuit ; |
Masque.Gratuit ; |
BinStream.Free ; |
fin; |
fin; |
fin. |
Ce qui suit montre comment l'utiliser dans Delphi : |
Créez d’abord un nouveau projet dans Delphi, puis placez un contrôle ImageListEx, un contrôle TreeView et quatre contrôles Button sur Form1. Associez la propriété Images du contrôle TreeView à ImageListEx, ajoutez n'importe quel nombre d'images à ImageListEx et ajoutez un nombre correspondant d'éléments à TreeView. Les propriétés ImageIndex des éléments correspondent aux numéros d'index des images dans ImageListEx. Désormais, l'icône correspondante peut être affichée avant chaque élément dans TreeView. |
Enfin, écrivez dans l'événement OnClick de Button1 : |
ImageListEx1.SaveToFile('C:CJ.dat'); |
ImageListEx1.SaveToFileEx('C:CJEx.dat'); |
Dans l'événement OnClick de Button2, écrivez : ImageListEx1.Clear ; |
Écrivez dans l'événement OnClick de Button3 : ImageListEx1.LoadFromFile('C:CJ.dat'); |
Écrivez dans l'événement OnClick de Button4 : ImageListEx1.LoadFromFileEx('C:CJEx.dat'); |
Exécutez le programme, cliquez d'abord sur Button1, puis sur Button2, et enfin sur Button3 ou Button4. Vous pouvez voir que le programme peut enregistrer les images de la liste d'images dans le fichier spécifié, et peut les restaurer et les afficher correctement à partir du fichier spécifié. . |
Conclusion |
Le contenu présenté dans cet article a été utilisé pour résoudre la situation que j'ai rencontrée dans des projets réels. J'espère également que les programmeurs qui rencontrent également ce problème pourront y trouver la réponse. Le code ci-dessus a réussi le débogage et s'exécute dans Delphi5.0 et Windows2000 Server. |