2 // System.Windows.Forms.ImageList.cs
5 // Peter Bartok <pbartok@novell.com>
6 // Kornél Pál <http://www.kornelpal.hu/>
8 // Copyright (C) 2004-2005 Novell, Inc.
9 // Copyright (C) 2005 Kornél Pál
13 // Permission is hereby granted, free of charge, to any person obtaining
14 // a copy of this software and associated documentation files (the
15 // "Software"), to deal in the Software without restriction, including
16 // without limitation the rights to use, copy, modify, merge, publish,
17 // distribute, sublicense, and/or sell copies of the Software, and to
18 // permit persons to whom the Software is furnished to do so, subject to
19 // the following conditions:
21 // The above copyright notice and this permission notice shall be
22 // included in all copies or substantial portions of the Software.
24 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
25 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
26 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
27 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
28 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
29 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
30 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
36 // Differences between MS.NET ImageList and this implementation:
38 // This is a fully managed image list implementation.
40 // Images are stored as Format32bppArgb internally but ColorDepth is applied
41 // to the colors of images. Images[index] returns a Format32bppArgb copy of
42 // the image so this difference is only internal.
44 // MS.NET has no alpha channel support (except for icons in 32-bit mode with
45 // comctl32.dll version 6.0) but this implementation has full alpha channel
46 // support in 32-bit mode.
48 // Handle should be an HIMAGELIST returned by ImageList_Create. This
49 // implementation uses (IntPtr)(-1) that is a non-zero but invalid handle.
51 // MS.NET destroys handles using the garbage collector this implementation
52 // does the same with Image objects stored in an ArrayList.
54 // MS.NET 1.x shares the same HIMAGELIST between ImageLists that were
55 // initialized from the same ImageListStreamer and doesn't update ImageSize
56 // and ColorDepth that are treated as bugs and MS.NET 2.0 behavior is
59 // MS.NET 2.0 initializes TransparentColor to Color.Transparent in
60 // constructors but ResetTransparentColor and ShouldSerializeTransparentColor
61 // default to Color.LightGray that is treated as a bug.
63 // MS.NET 2.0 does not clear keys when handle is destroyed that is treated as
67 using System.Collections;
68 using System.Collections.Specialized;
69 using System.ComponentModel;
70 using System.ComponentModel.Design.Serialization;
72 using System.Drawing.Design;
73 using System.Drawing.Imaging;
74 using System.Globalization;
75 using System.Runtime.InteropServices;
77 namespace System.Windows.Forms
79 [DefaultProperty("Images")]
80 [Designer("System.Windows.Forms.Design.ImageListDesigner, " + Consts.AssemblySystem_Design)]
82 [DesignerSerializer("System.Windows.Forms.Design.ImageListCodeDomSerializer, " + Consts.AssemblySystem_Design, "System.ComponentModel.Design.Serialization.CodeDomSerializer, " + Consts.AssemblySystem_Design)]
84 [ToolboxItemFilter("System.Windows.Forms")]
85 [TypeConverter(typeof(ImageListConverter))]
86 public sealed class ImageList : System.ComponentModel.Component
88 #region Private Fields
89 private const ColorDepth DefaultColorDepth = ColorDepth.Depth8Bit;
90 private static readonly Color DefaultTransparentColor = Color.Transparent;
91 private static readonly Size DefaultImageSize = new Size(16, 16);
96 private EventHandler recreateHandle;
97 private readonly ImageCollection images;
98 #endregion // Private Fields
101 [Editor("System.Windows.Forms.Design.ImageCollectionEditor, " + Consts.AssemblySystem_Design, typeof(UITypeEditor))]
102 public sealed class ImageCollection : IList, ICollection, IEnumerable
104 private const int AlphaMask = unchecked((int)0xFF000000);
106 [StructLayout(LayoutKind.Explicit)]
107 private struct ArgbColor
127 class IndexedColorDepths
130 private IndexedColorDepths()
134 internal static readonly ArgbColor[] Palette4Bit;
135 internal static readonly ArgbColor[] Palette8Bit;
136 private static readonly int[] squares;
138 static IndexedColorDepths()
145 bitmap = new Bitmap(1, 1, PixelFormat.Format4bppIndexed);
146 palette = bitmap.Palette.Entries;
149 Palette4Bit = new ArgbColor[count = palette.Length];
150 for (index = 0; index < count; index++)
151 Palette4Bit[index].Argb = palette[index].ToArgb();
153 bitmap = new Bitmap(1, 1, PixelFormat.Format8bppIndexed);
154 palette = bitmap.Palette.Entries;
157 Palette8Bit = new ArgbColor[count = palette.Length];
158 for (index = 0; index < count; index++)
159 Palette8Bit[index].Argb = palette[index].ToArgb();
161 squares = new int[511];
162 for (index = 0; index < 256; index++)
163 squares[255 + index] = squares[255 - index] = index * index;
166 internal static int GetNearestColor(ArgbColor[] palette, int color)
177 count = palette.Length;
178 for (index = 0; index < count; index++)
179 if (palette[index].Argb == color)
182 red = unchecked((int)(unchecked((uint)color) >> 16) & 0xFF);
183 green = unchecked((int)(unchecked((uint)color) >> 8) & 0xFF);
185 nearestColor = AlphaMask;
186 minDistance = int.MaxValue;
188 for (index = 0; index < count; index++)
189 if ((distance = squares[255 + palette[index].Red - red] + squares[255 + palette[index].Green - green] + squares[255 + palette[index].Blue - blue]) < minDistance) {
190 nearestColor = palette[index].Argb;
191 minDistance = distance;
199 private enum ItemFlags
202 UseTransparentColor = 1,
206 private sealed class ImageListItem
208 internal readonly object Image;
209 internal readonly ItemFlags Flags;
210 internal readonly Color TransparentColor;
211 internal readonly int ImageCount = 1;
213 internal ImageListItem(Icon value)
216 throw new ArgumentNullException("value");
219 this.Image = (Icon)value.Clone();
222 internal ImageListItem(Image value)
225 throw new ArgumentNullException("value");
227 if (!(value is Bitmap))
228 throw new ArgumentException("Image must be a Bitmap.");
230 // Images are not cloned.
234 internal ImageListItem(Image value, Color transparentColor) : this(value)
236 this.Flags = ItemFlags.UseTransparentColor;
237 this.TransparentColor = transparentColor;
240 internal ImageListItem(Image value, int imageCount) : this(value)
242 this.Flags = ItemFlags.ImageStrip;
243 this.ImageCount = imageCount;
247 #region ImageCollection Private Fields
248 private ColorDepth colorDepth = DefaultColorDepth;
249 private Color transparentColor = DefaultTransparentColor;
250 private Size imageSize = DefaultImageSize;
251 private ArrayList list = new ArrayList();
253 private ArrayList keys = new ArrayList();
256 private bool handleCreated;
258 private int lastKeyIndex = -1;
260 private readonly ImageList owner;
261 #endregion // ImageCollection Private Fields
263 #region ImageCollection Internal Constructors
264 // For use in ImageList
265 internal ImageCollection(ImageList owner)
269 #endregion // ImageCollection Internal Constructor
271 #region ImageCollection Internal Instance Properties
272 // For use in ImageList
273 internal ColorDepth ColorDepth {
275 return this.colorDepth;
279 if (!Enum.IsDefined(typeof(ColorDepth), value))
280 throw new InvalidEnumArgumentException("value", (int)value, typeof(ColorDepth));
282 if (this.colorDepth != value) {
283 this.colorDepth = value;
289 // For use in ImageList
290 internal IntPtr Handle {
297 // For use in ImageList
298 internal bool HandleCreated {
300 return this.handleCreated;
304 // For use in ImageList
305 internal Size ImageSize {
307 return this.imageSize;
311 if (value.Width < 1 || value.Width > 256 || value.Height < 1 || value.Height > 256)
312 throw new ArgumentException("ImageSize.Width and Height must be between 1 and 256", "value");
314 if (this.imageSize != value) {
315 this.imageSize = value;
321 // For use in ImageList
322 internal ImageListStreamer ImageStream {
324 return this.Empty ? null : new ImageListStreamer(this);
329 Image[] streamImages;
333 if (this.handleCreated)
339 // Only deserialized ImageListStreamers are used.
340 else if ((streamImages = value.Images) != null) {
341 this.list = new ArrayList(streamImages.Length);
343 this.handleCreated = true;
345 this.keys = new ArrayList(streamImages.Length);
348 for (index = 0; index < streamImages.Length; index++) {
349 list.Add((Image)streamImages[index].Clone());
355 this.imageSize = value.ImageSize;
356 this.colorDepth = value.ColorDepth;
359 // Event is raised even when handle was not created yet.
360 owner.OnRecreateHandle();
366 // For use in ImageList
367 internal Color TransparentColor {
369 return this.transparentColor;
373 this.transparentColor = value;
376 #endregion // ImageCollection Internal Instance Properties
378 #region ImageCollection Public Instance Properties
382 return this.handleCreated ? list.Count : this.count;
388 return this.Count == 0;
392 public bool IsReadOnly {
399 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
400 public Image this[int index] {
402 return (Image)GetImage(index).Clone();
408 if (index < 0 || index >= this.Count)
409 throw new ArgumentOutOfRangeException("index");
412 throw new ArgumentNullException("value");
414 if (!(value is Bitmap))
415 throw new ArgumentException("Image must be a Bitmap.");
417 image = CreateImage(value, this.transparentColor);
424 public Image this[string key] {
428 return (index = IndexOfKey(key)) == -1 ? null : this[index];
432 public StringCollection Keys {
436 StringCollection keyCollection;
438 // Returns all keys even when there are more keys than
439 // images. Null keys are returned as empty strings.
441 keyCollection = new StringCollection();
442 for (index = 0; index < keys.Count; index++)
443 keyCollection.Add(((key = (string)keys[index]) == null || key.Length == 0) ? string.Empty : key);
445 return keyCollection;
449 #endregion // ImageCollection Public Instance Properties
451 #region ImageCollection Private Static Methods
453 private static bool CompareKeys(string key1, string key2)
455 // Keys are case-insensitive and keys with different length
456 // are not equal even when string.Compare treats them equal.
458 if (key1 == null || key2 == null || key1.Length != key2.Length)
461 return string.Compare(key1, key2, true, CultureInfo.InvariantCulture) == 0;
464 #endregion // ImageCollection Private Static Methods
466 #region ImageCollection Private Instance Methods
468 private int AddItem(string key, ImageListItem item)
470 private int AddItem(ImageListItem item)
478 if (this.handleCreated)
479 itemIndex = AddItemInternal(item);
481 // Image strips are counted as a single item in the return
482 // value of Add and AddStrip until handle is created.
484 itemIndex = list.Add(item);
485 this.count += item.ImageCount;
489 if ((item.Flags & ItemFlags.ImageStrip) == 0)
492 for (index = 0; index < item.ImageCount; index++)
499 private int AddItemInternal(ImageListItem item)
501 if (item.Image is Icon) {
507 bitmap = new Bitmap(imageWidth = this.imageSize.Width, imageHeight = this.imageSize.Height, PixelFormat.Format32bppArgb);
508 graphics = Graphics.FromImage(bitmap);
509 graphics.DrawIcon((Icon)item.Image, new Rectangle(0, 0, imageWidth, imageHeight));
512 ReduceColorDepth(bitmap);
513 return list.Add(bitmap);
515 else if ((item.Flags & ItemFlags.ImageStrip) == 0)
516 return list.Add(CreateImage((Image)item.Image, (item.Flags & ItemFlags.UseTransparentColor) == 0 ? this.transparentColor : item.TransparentColor));
527 ImageAttributes imageAttributes;
529 // When ImageSize was changed after adding image strips
530 // Count will return invalid values based on old ImageSize
531 // but when creating handle either ArgumentException will
532 // be thrown or image strip will be added according to the
533 // new ImageSize. This can result in image count
534 // difference that can result in exceptions in methods
535 // that use Count before creating handle. In addition this
536 // can result in the loss of sync with keys. When doing
537 // the same after handle was created there are no problems
538 // as handle will be recreated after changing ImageSize
539 // that results in the loss of images added previously.
541 if ((width = (image = (Image)item.Image).Width) == 0 || (width % (imageWidth = this.imageSize.Width)) != 0)
542 throw new ArgumentException("Width of image strip must be a positive multiple of ImageSize.Width.", "value");
544 if (image.Height != (imageHeight = this.imageSize.Height))
545 throw new ArgumentException("Height of image strip must be equal to ImageSize.Height.", "value");
547 imageRect = new Rectangle(0, 0, imageWidth, imageHeight);
548 if (this.transparentColor.A == 0)
549 imageAttributes = null;
551 imageAttributes = new ImageAttributes();
552 imageAttributes.SetColorKey(this.transparentColor, this.transparentColor);
556 for (imageX = 0; imageX < width; imageX += imageWidth) {
557 bitmap = new Bitmap(imageWidth, imageHeight, PixelFormat.Format32bppArgb);
558 graphics = Graphics.FromImage(bitmap);
559 graphics.DrawImage(image, imageRect, imageX, 0, imageWidth, imageHeight, GraphicsUnit.Pixel, imageAttributes);
562 ReduceColorDepth(bitmap);
566 if (imageAttributes != null)
567 imageAttributes.Dispose();
573 private void CreateHandle()
578 if (!this.handleCreated) {
580 this.list = new ArrayList(this.count);
582 this.handleCreated = true;
584 for (index = 0; index < items.Count; index++)
585 AddItemInternal((ImageListItem)items[index]);
589 private Image CreateImage(Image value, Color transparentColor)
595 ImageAttributes imageAttributes;
597 if (transparentColor.A == 0)
598 imageAttributes = null;
600 imageAttributes = new ImageAttributes();
601 imageAttributes.SetColorKey(transparentColor, transparentColor);
604 bitmap = new Bitmap(imageWidth = this.imageSize.Width, imageHeight = this.imageSize.Height, PixelFormat.Format32bppArgb);
605 graphics = Graphics.FromImage(bitmap);
606 graphics.DrawImage(value, new Rectangle(0, 0, imageWidth, imageHeight), 0, 0, value.Width, value.Height, GraphicsUnit.Pixel, imageAttributes);
609 if (imageAttributes != null)
610 imageAttributes.Dispose();
612 ReduceColorDepth(bitmap);
616 private void RecreateHandle()
618 if (this.handleCreated) {
620 this.handleCreated = true;
621 owner.OnRecreateHandle();
625 private unsafe void ReduceColorDepth(Bitmap bitmap)
635 BitmapData bitmapData;
638 if (this.colorDepth < ColorDepth.Depth32Bit) {
639 bitmapData = bitmap.LockBits(new Rectangle(0, 0, bitmap.Width, bitmap.Height), ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb);
641 linePtr = (byte*)bitmapData.Scan0;
642 height = bitmapData.Height;
643 widthBytes = bitmapData.Width << 2;
644 stride = bitmapData.Stride;
646 if (this.colorDepth < ColorDepth.Depth16Bit) {
647 palette = this.colorDepth < ColorDepth.Depth8Bit ? IndexedColorDepths.Palette4Bit : IndexedColorDepths.Palette8Bit;
649 for (line = 0; line < height; line++) {
650 lineEndPtr = linePtr + widthBytes;
651 for (pixelPtr = linePtr; pixelPtr < lineEndPtr; pixelPtr += 4)
652 *(int*)pixelPtr = ((pixel = *(int*)pixelPtr) & AlphaMask) == 0 ? 0x00000000 : IndexedColorDepths.GetNearestColor(palette, pixel | AlphaMask);
656 else if (this.colorDepth < ColorDepth.Depth24Bit) {
657 for (line = 0; line < height; line++) {
658 lineEndPtr = linePtr + widthBytes;
659 for (pixelPtr = linePtr; pixelPtr < lineEndPtr; pixelPtr += 4)
660 *(int*)pixelPtr = ((pixel = *(int*)pixelPtr) & AlphaMask) == 0 ? 0x00000000 : (pixel & 0x00F8F8F8) | AlphaMask;
665 for (line = 0; line < height; line++) {
666 lineEndPtr = linePtr + widthBytes;
667 for (pixelPtr = linePtr; pixelPtr < lineEndPtr; pixelPtr += 4)
668 *(int*)pixelPtr = ((pixel = *(int*)pixelPtr) & AlphaMask) == 0 ? 0x00000000 : pixel | AlphaMask;
674 bitmap.UnlockBits(bitmapData);
678 #endregion // ImageCollection Private Instance Methods
680 #region ImageCollection Internal Instance Methods
681 // For use in ImageList
682 internal void DestroyHandle()
684 if (this.handleCreated) {
685 this.list = new ArrayList();
687 this.handleCreated = false;
689 keys = new ArrayList();
694 // For use in ImageList
695 internal Image GetImage(int index)
697 if (index < 0 || index >= this.Count)
698 throw new ArgumentOutOfRangeException("index");
701 return (Image)list[index];
704 // For use in ImageListStreamer
705 internal Image[] ToArray()
709 // Handle is created even when the list is empty.
711 images = new Image[list.Count];
715 #endregion // ImageCollection Internal Instance Methods
717 #region ImageCollection Public Instance Methods
718 public void Add(Icon value)
723 AddItem(new ImageListItem(value));
727 public void Add(Image value)
732 AddItem(new ImageListItem(value));
736 public int Add(Image value, Color transparentColor)
739 return AddItem(null, new ImageListItem(value, transparentColor));
741 return AddItem(new ImageListItem(value, transparentColor));
746 public void Add(string key, Icon icon)
748 // Argument has name icon but exceptions use name value.
749 AddItem(key, new ImageListItem(icon));
752 public void Add(string key, Image image)
754 // Argument has name image but exceptions use name value.
755 AddItem(key, new ImageListItem(image));
758 public void AddRange(Image[] images)
763 throw new ArgumentNullException("images");
765 for (index = 0; index < images.Length; index++)
770 public int AddStrip(Image value)
776 throw new ArgumentNullException("value");
778 if ((width = value.Width) == 0 || (width % (imageWidth = this.imageSize.Width)) != 0)
779 throw new ArgumentException("Width of image strip must be a positive multiple of ImageSize.Width.", "value");
781 if (value.Height != this.imageSize.Height)
782 throw new ArgumentException("Height of image strip must be equal to ImageSize.Height.", "value");
785 return AddItem(null, new ImageListItem(value, width / imageWidth));
787 return AddItem(new ImageListItem(value, width / imageWidth));
794 if (this.handleCreated)
802 [EditorBrowsable(EditorBrowsableState.Never)]
804 public bool Contains(Image image)
806 throw new NotSupportedException();
810 public bool ContainsKey(string key)
812 return IndexOfKey(key) != -1;
816 public IEnumerator GetEnumerator()
818 Image[] images = new Image[this.Count];
821 if (images.Length != 0) {
822 // Handle is created only when there are images.
825 for (index = 0; index < images.Length; index++)
826 images[index] = (Image)((Image)list[index]).Clone();
829 return images.GetEnumerator();
833 [EditorBrowsable(EditorBrowsableState.Never)]
835 public int IndexOf(Image image)
837 throw new NotSupportedException();
841 public int IndexOfKey(string key)
845 if (key != null && key.Length != 0) {
846 // When last IndexOfKey was successful and the same key was
847 // assigned to an image with a lower index than the last
848 // result and the key of the last result equals to key
849 // argument the last result is returned.
851 if (this.lastKeyIndex >= 0 && this.lastKeyIndex < this.Count && CompareKeys((string)keys[this.lastKeyIndex], key))
852 return this.lastKeyIndex;
854 // Duplicate keys are allowed and first match is returned.
855 for (index = 0; index < this.Count; index++)
856 if (CompareKeys((string)keys[index], key))
857 return this.lastKeyIndex = index;
860 return this.lastKeyIndex = -1;
865 [EditorBrowsable(EditorBrowsableState.Never)]
867 public void Remove(Image image)
869 throw new NotSupportedException();
872 public void RemoveAt(int index)
874 if (index < 0 || index >= this.Count)
875 throw new ArgumentOutOfRangeException("index");
878 list.RemoveAt(index);
880 keys.RemoveAt(index);
885 public void RemoveByKey(string key)
889 if ((index = IndexOfKey(key)) != -1)
893 public void SetKeyName(int index, string name)
895 // Only SetKeyName throws IndexOutOfRangeException.
896 if (index < 0 || index >= this.Count)
897 throw new IndexOutOfRangeException();
902 #endregion // ImageCollection Public Instance Methods
904 #region ImageCollection Interface Properties
905 object IList.this[int index] {
911 if (!(value is Image))
912 throw new ArgumentException("value");
914 this[index] = (Image)value;
918 bool IList.IsFixedSize {
924 bool ICollection.IsSynchronized {
930 object ICollection.SyncRoot {
935 #endregion // ImageCollection Interface Properties
937 #region ImageCollection Interface Methods
938 int IList.Add(object value)
942 if (!(value is Image))
943 throw new ArgumentException("value");
946 this.Add((Image)value);
950 bool IList.Contains(object value)
952 return value is Image ? this.Contains((Image)value) : false;
955 int IList.IndexOf(object value)
957 return value is Image ? this.IndexOf((Image)value) : -1;
960 void IList.Insert(int index, object value)
962 throw new NotSupportedException();
965 void IList.Remove(object value)
968 this.Remove((Image)value);
971 void ICollection.CopyTo(Array array, int index)
975 for (imageIndex = 0; imageIndex < this.Count; imageIndex++)
976 array.SetValue(this[index], index++);
978 #endregion // ImageCollection Interface Methods
980 #endregion // Sub-classes
982 #region Public Constructors
985 images = new ImageCollection(this);
988 public ImageList(System.ComponentModel.IContainer container) : this()
992 #endregion // Public Constructors
994 #region Private Instance Methods
995 private void OnRecreateHandle()
997 if (recreateHandle != null)
998 recreateHandle(this, EventArgs.Empty);
1002 // For use in Designers
1003 private void ResetColorDepth()
1005 this.ColorDepth = DefaultColorDepth;
1008 // For use in Designers
1009 private void ResetImageSize()
1011 this.ImageSize = DefaultImageSize;
1014 // For use in Designers
1015 private void ResetTransparentColor()
1017 this.TransparentColor = DefaultTransparentColor;
1020 // For use in Designers
1021 private bool ShouldSerializeColorDepth()
1023 // ColorDepth is serialized in ImageStream when non-empty.
1024 // It is serialized even if it has its default value when empty.
1025 return images.Empty;
1028 // For use in Designers
1029 private bool ShouldSerializeImageSize()
1031 // ImageSize is serialized in ImageStream when non-empty.
1032 // It is serialized even if it has its default value when empty.
1033 return images.Empty;
1036 // For use in Designers
1037 private bool ShouldSerializeTransparentColor()
1039 return this.TransparentColor != DefaultTransparentColor;
1042 #endregion // Private Instance Methods
1044 #region Public Instance Properties
1046 [DefaultValue(DefaultColorDepth)]
1048 public ColorDepth ColorDepth {
1050 return images.ColorDepth;
1054 images.ColorDepth = value;
1059 [EditorBrowsable(EditorBrowsableState.Advanced)]
1060 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
1061 public IntPtr Handle {
1063 return images.Handle;
1068 [EditorBrowsable(EditorBrowsableState.Advanced)]
1069 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
1070 public bool HandleCreated {
1072 return images.HandleCreated;
1076 [DefaultValue(null)]
1077 [MergableProperty(false)]
1078 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
1079 public ImageCollection Images {
1086 public Size ImageSize {
1088 return images.ImageSize;
1092 images.ImageSize = value;
1097 [DefaultValue(null)]
1098 [EditorBrowsable(EditorBrowsableState.Advanced)]
1099 public ImageListStreamer ImageStream {
1101 return images.ImageStream;
1105 images.ImageStream = value;
1111 [DefaultValue(null)]
1112 [Localizable(false)]
1113 [TypeConverter(typeof(StringConverter))]
1125 public Color TransparentColor {
1127 return images.TransparentColor;
1131 images.TransparentColor = value;
1134 #endregion // Public Instance Properties
1136 #region Public Instance Methods
1137 public void Draw(Graphics g, Point pt, int index)
1139 this.Draw(g, pt.X, pt.Y, index);
1142 public void Draw(Graphics g, int x, int y, int index)
1144 g.DrawImage(images.GetImage(index), x, y);
1147 public void Draw(Graphics g, int x, int y, int width, int height, int index)
1149 g.DrawImage(images.GetImage(index), x, y, width, height);
1152 public override string ToString()
1154 return base.ToString() + " Images.Count: " + images.Count.ToString() + ", ImageSize: " + images.ImageSize.ToString();
1156 #endregion // Public Instance Methods
1158 #region Protected Instance Methods
1159 protected override void Dispose(bool disposing)
1162 images.DestroyHandle();
1164 base.Dispose(disposing);
1166 #endregion // Protected Instance Methods
1170 [EditorBrowsable(EditorBrowsableState.Advanced)]
1171 public event EventHandler RecreateHandle {
1173 recreateHandle += value;
1177 recreateHandle -= value;
1180 #endregion // Events