Baru-baru ini, ketika mengerjakan sebuah proyek, saya menghadapi situasi menyimpan serangkaian gambar dalam daftar gambar (TImageList) ke file tertentu atau aliran biner sehingga dapat dipulihkan secara dinamis saat diperlukan. Jadi saya mencari properti dan metode yang terkait dengan kelas TImageList di bantuan Delphi. Sayangnya, Delphi tidak menyediakan metode SaveToFile dan SaveToStream di TImageList. Oleh karena itu, mengingat keterbatasan TImageList saat ini, metode lain harus diadopsi untuk memperluas fungsi TImageList untuk memenuhi kebutuhan proyek sebenarnya. |
Larutan |
Metode satu: |
Gunakan fungsi API ImageList_Write dan ImageList_Read. Keduanya perlu menentukan parameter tipe IStream. Fungsi yang pertama adalah untuk menyimpan daftar gambar dari pegangan yang ditentukan ke dalam aliran biner tipe IStream; ., dan mengembalikan pegangan ke daftar gambar ini. IStream adalah objek OLE, dan deklarasinya di Delphi adalah TStreamAdapter = class(TInterfacedObject, IStream), yang berarti TStreamAdapter adalah objek warisan dari TInterfacedObject yang memanipulasi antarmuka IStream. Melalui objek TStreamAdapter, manipulasi objek antarmuka IStream oleh objek TStream internal Delphi dapat direalisasikan. |
Metode dua: |
Mewarisi subkelas TImageListEx dari TImageList dan menerapkan metode SaveToFileEx dan SaveToStreamEx khusus. Secara default, gambar yang disimpan di TImageList terdiri dari gambar biasa dan gambar topengnya, sehingga GetImages(Indeks: Integer; Gambar, Mask: disediakan oleh bagian yang dilindungi dari kelas dasarnya TCustomImageList harus dipanggil) TBitmap) untuk mendapatkan bitmap dengan nomor indeks yang ditentukan dalam daftar gambar dan bitmap topengnya, lalu menyimpannya masing-masing ke file khusus atau aliran biner. Selain itu, metode LoadFromFileEx dan LoadFromStreamEx juga diperlukan untuk mendapatkan bitmap file khusus atau aliran biner. |
Langkah-langkah implementasi |
Kontrol TImageListEx khusus merangkum dua metode di atas di bagian Publik. |
Kode sumber kelas TImageListEx adalah sebagai berikut: |
satuan Daftar GambarEx; |
antarmuka |
menggunakan Windows, SysUtils, Kelas, Grafik, Kontrol, Commctrl, ImgList, Consts; |
jenis |
TImageListEx = kelas(TImageList) |
publik |
procedure LoadFromFile(const FileName: string);//Terapkan metode API untuk menyimpan |
prosedur LoadFromStream(Stream: TStream); |
prosedur SaveToFile(const Nama File: string); |
prosedur SaveToStream(Stream: TStream); |
procedure LoadFromFileEx(const FileName: string);//Mencapai metode penyimpanan khusus |
prosedur LoadFromStreamEx(Stream: TStream); |
prosedur SaveToFileEx(const Nama File: string); |
prosedur SaveToStreamEx(Stream: TStream); |
akhir; |
prosedur Daftar; |
pelaksanaan |
prosedur Daftar; |
mulai |
RegisterComponents('ImageListEx', [TImageListEx]); |
akhir; |
{TIimageListEx} |
prosedur TImageListEx.LoadFromFile(const Nama File: string); |
var |
Aliran: TSstream; |
mulai |
Aliran := TFileStream.Create(Nama File, fmOpenRead); |
mencoba |
LoadFromStream(Aliran); |
Akhirnya |
Streaming.Gratis; |
akhir; |
akhir; |
prosedur TImageListEx.LoadFromFileEx(const Nama File: string); |
var |
Aliran: TSstream; |
mulai |
Aliran := TFileStream.Create(Nama File, fmOpenRead); |
mencoba |
LoadFromStreamEx(Aliran); |
Akhirnya |
Streaming.Gratis; |
akhir; |
akhir; |
prosedur TImageListEx.LoadFromStream(Stream: TStream); |
var |
SA: Adaptor TStream; |
mulai |
SA := TStreamAdapter.Create(Stream); |
mencoba |
Menangani := ImageList_Read(SA);//Arahkan pegangan daftar gambar saat ini ke pegangan yang diperoleh dari aliran biner |
jika Pegangan = 0 maka |
naikkan EReadError.CreateRes(@SImageReadFail); |
Akhirnya |
SA.Gratis; |
akhir; |
akhir; |
prosedur TImageListEx.LoadFromStreamEx(Stream: TStream); |
var |
Lebar, Tinggi: Bilangan Bulat; |
Bitmap, Topeng: TBitmap; |
BinStream: TMemoryStream; |
prosedur LoadImageFromStream(Gambar: TBitmap); |
var |
Hitung: DWord; |
mulai |
Gambar.Tugas(nihil); |
Stream.ReadBuffer(Count, SizeOf(Count));//Pertama baca ukuran bitmap |
BinStream.Hapus; |
BinStream.CopyFrom(Stream, Count);//Kemudian baca bitmapnya |
BinStream.Position := 0; //Reset penunjuk aliran |
Gambar.LoadFromStream(BinStream); |
akhir; |
mulai |
Stream.ReadBuffer(Tinggi, SizeOf(Tinggi)); |
Stream.ReadBuffer(Lebar, SizeOf(Lebar)); |
Diri.Tinggi := Tinggi; |
Self.Width := Lebar;//Kembalikan tinggi dan lebar asli daftar gambar |
Bitmap := TBitmap.Buat; |
Topeng := TBitmap.Buat; |
BinStream := TMemoryStream.Buat; |
mencoba |
sementara Stream.Position <> Stream.Size lakukan |
mulai |
LoadImageFromStream(Bitmap);//Baca bitmap dari aliran biner |
LoadImageFromStream(Mask);//Baca bitmap mask dari aliran biner |
Tambahkan(Bitmap, Mask);//Tambahkan bitmap dan bitmap masknya ke daftar gambar |
akhir; |
Akhirnya |
Bitmap.Gratis; |
Masker.Gratis; |
BinStream.Gratis; |
akhir; |
akhir; |
prosedur TImageListEx.SaveToFile(const Nama File: string); |
var |
Aliran: TSstream; |
mulai |
Aliran := TFileStream.Create(Nama File, fmCreate); |
mencoba |
SimpanKeStream(Aliran); |
Akhirnya |
Streaming.Gratis; |
akhir; |
akhir; |
prosedur TImageListEx.SaveToFileEx(const Nama File: string); |
var |
Aliran: TSstream; |
mulai |
Aliran := TFileStream.Create(Nama File, fmCreate); |
mencoba |
SaveToStreamEx(Aliran); |
Akhirnya |
Streaming.Gratis; |
akhir; |
akhir; |
prosedur TImageListEx.SaveToStream(Stream: TStream); |
var |
SA: Adaptor TStream; |
mulai |
SA := TStreamAdapter.Create(Stream); |
mencoba |
jika bukan ImageList_Write(Handle, SA) maka//Simpan daftar gambar saat ini ke aliran biner |
naikkan EWriteError.CreateRes(@SImageWriteFail); |
Akhirnya |
SA.Gratis; |
akhir; |
akhir; |
prosedur TImageListEx.SaveToStreamEx(Stream: TStream); |
var |
Saya: Bilangan Bulat; |
Lebar, Tinggi: Bilangan Bulat; |
Bitmap, Topeng: TBitmap; |
BinStream: TMemoryStream; |
prosedur SetImage(Gambar: TBitmap; IsMask: Boolean); |
mulai |
Image.Assign(nil);//Hapus gambar yang terakhir disimpan untuk menghindari gambar tumpang tindih |
dengan Gambar lakukan |
mulai |
jika IsMask maka MonoChrome := True;//Bitmap mask harus menggunakan monokrom |
Tinggi := Diri.Tinggi; |
Lebar := Diri.Lebar; |
akhir; |
akhir; |
prosedur SaveImageToStream(Gambar: TBitmap); |
var |
Hitung: DWORD; |
mulai |
BinStream.Hapus; |
Gambar.SaveToStream(BinStream); |
Hitung := BinStream.Ukuran; |
Stream.WriteBuffer(Count, SizeOf(Count));//Pertama simpan ukuran bitmap |
Stream.CopyFrom(BinStream, 0);//Kemudian simpan bitmapnya |
akhir; |
mulai |
Tinggi := Diri.Tinggi; |
Lebar := Diri.Lebar; |
Stream.WriteBuffer(Height, SizeOf(Height));//Simpan tinggi daftar gambar asli |
Stream.WriteBuffer(Width, SizeOf(Width));//Simpan lebar daftar gambar asli |
Bitmap := TBitmap.Buat; |
Topeng := TBitmap.Buat; |
BinStream := TMemoryStream.Buat; |
mencoba |
for I := 0 to Count - 1 do//Simpan gambar dalam daftar gambar |
mulai |
SetImage(Bitmap, Salah); |
SetImage(Masker, Benar); |
GetImages(I, Bitmap, Mask);//Dapatkan bitmap dengan nomor indeks yang ditentukan dan bitmap masknya |
SaveImageToStream(Bitmap);//Simpan bitmap ke aliran biner |
SaveImageToStream(Mask);//Simpan bitmap mask ke aliran biner |
akhir; |
Akhirnya |
Bitmap.Gratis; |
Masker.Gratis; |
BinStream.Gratis; |
akhir; |
akhir; |
akhir. |
Berikut ini menunjukkan cara menggunakannya di Delphi: |
Pertama buat proyek baru di Delphi, dan kemudian tempatkan kontrol ImageListEx, kontrol TreeView dan empat kontrol Tombol pada Form1. Kaitkan properti Gambar dari kontrol TreeView dengan ImageListEx, tambahkan sejumlah gambar ke ImageListEx, dan tambahkan jumlah item yang sesuai ke TreeView. Properti ImageIndex item sesuai dengan nomor indeks gambar di ImageListEx. Sekarang ikon terkait dapat ditampilkan sebelum setiap item di TreeView. |
Terakhir, tulis di event OnClick Button1: |
ImageListEx1.SaveToFile('C:CJ.dat'); |
ImageListEx1.SaveToFileEx('C:CJEx.dat'); |
Dalam acara OnClick Button2 tulis: ImageListEx1.Clear; |
Tulis di acara OnClick Button3: ImageListEx1.LoadFromFile('C:CJ.dat'); |
Tulis di acara OnClick Button4: ImageListEx1.LoadFromFileEx('C:CJEx.dat'); |
Jalankan programnya, pertama klik Button1, lalu klik Button2, dan terakhir klik Button3 atau Button4. Anda dapat melihat bahwa program dapat menyimpan gambar dalam daftar gambar ke file yang ditentukan, dan dapat memulihkan dan menampilkannya dengan benar dari file yang ditentukan. . |
Kesimpulan |
Konten yang diperkenalkan dalam artikel ini telah digunakan untuk memecahkan situasi yang saya temui di proyek sebenarnya. Saya juga berharap programmer yang juga mengalami masalah ini dapat menemukan jawabannya. Kode di atas telah melewati debugging dan berjalan di Delphi5.0 dan Windows2000 Server. |