ImageList半透明,Alpha通道bug处理。
由于ImageList的先天障碍,对alpha通道支持不好。虽然到xp有所改善,但瑕疵依然存在。
通过reflactor发现ImageList通过windows api来进行读写的。写入数据时会对原始图像进行处理,等到读取时已经获取不到原始图像。鉴于此,只能另起炉灶重新编写一个ImageList,也就是缩略图集合类。
思路:
1,应该有缩略图大小属性,由于添加图像后生成缩略图,并与原始图像断绝关系。所以在有缩略图的情况下不允许修改大小。
2,缩略图集合。可增加图像到集合,添加时按指定大小生成缩略图。可通过索引检索以便调用。删除或清空时要释放生成的资源。
好了,以上就是主题思想。下面是代码。
ImageListEx类代码
1 /// <summary> 2 /// 缩略图集合 3 /// </summary> 4 public sealed partial class ImageListEx : Component 5 { 6 private object m_Tag; 7 /// <summary> 8 /// 附加数据 9 /// </summary> 10 [DefaultValue(null), TypeConverter(typeof(StringConverter))] 11 public object Tag 12 { 13 get 14 { 15 return this.m_Tag; 16 } 17 set 18 { 19 this.m_Tag = value; 20 } 21 } 22 23 private Size m_Size = new Size(32, 32); 24 /// <summary> 25 /// 缩略图大小,只能先设置大小后添加图片 26 /// </summary> 27 [DefaultValue(typeof(Size), "32,32")] 28 public Size ImageSize 29 { 30 get 31 { 32 return this.m_Size; 33 } 34 35 set 36 { 37 if (value.Width <= 0 || value.Height <= 0 || this.ImageThumbs.Count > 0) 38 return; 39 40 this.m_Size = value; 41 } 42 } 43 44 private ThumbCollection m_ImageThumbs; 45 /// <summary> 46 /// 缩略图,只能先设置大小后添加图片 47 /// </summary> 48 [DefaultValue(null), DesignerSerializationVisibility(DesignerSerializationVisibility.Content), MergableProperty(false)] 49 public ThumbCollection ImageThumbs 50 { 51 get 52 { 53 if (this.m_ImageThumbs == null) 54 this.m_ImageThumbs = new ThumbCollection(this); 55 56 return this.m_ImageThumbs; 57 } 58 } 59 60 61 /// <summary> 62 /// 构造函数 63 /// </summary> 64 public ImageListEx() 65 { 66 } 67 68 /// <summary> 69 /// 构造函数 70 /// </summary> 71 /// <param name="container">容器</param> 72 public ImageListEx(IContainer container) 73 { 74 container.Add(this); 75 } 76 77 78 /// <summary> 79 /// 转换为字符串 80 /// </summary> 81 /// <returns>字符串</returns> 82 public override string ToString() 83 { 84 string str = base.ToString(); 85 if (this.m_ImageThumbs != null) 86 { 87 return (str + " ImageThumbs.Count: " + this.m_ImageThumbs.Count.ToString(CultureInfo.CurrentCulture) + ", ImageSize: " + this.ImageSize.ToString()); 88 } 89 return str; 90 } 91 92 /// <summary> 93 /// 清理所有正在使用的资源。 94 /// </summary> 95 /// <param name="disposing">如果应释放托管资源,为 true;否则为 false。</param> 96 protected override void Dispose(bool disposing) 97 { 98 if (this.m_ImageThumbs != null) 99 this.m_ImageThumbs.Dispose(); 100 101 base.Dispose(disposing); 102 } 103 }
ImageListEx.ImageInfo类代码
1 public partial class ImageListEx 2 { 3 /// <summary> 4 /// 图像信息 5 /// </summary> 6 public class ImageInfo 7 { 8 private string m_Name; 9 /// <summary> 10 /// 名称说明 11 /// </summary> 12 [DefaultValue(null)] 13 public string Name 14 { 15 get 16 { 17 return this.m_Name; 18 } 19 20 set 21 { 22 this.m_Name = value; 23 } 24 } 25 26 private Image m_Image; 27 /// <summary> 28 /// 图像 29 /// </summary> 30 [DefaultValue(null)] 31 public Image Image 32 { 33 get 34 { 35 return this.m_Image; 36 } 37 38 set 39 { 40 this.m_Image = value; 41 } 42 } 43 44 /// <summary> 45 /// 构造函数 46 /// </summary> 47 public ImageInfo() 48 { 49 } 50 51 /// <summary> 52 /// 构造函数 53 /// </summary> 54 /// <param name="name">名称说明</param> 55 /// <param name="image">图像</param> 56 public ImageInfo(string name, Image image) 57 { 58 this.m_Name = name; 59 this.m_Image = image; 60 } 61 } 62 }
ImageListEx.ThumbCollection类代码
1 public partial class ImageListEx 2 { 3 /// <summary> 4 /// 缩略图集合 5 /// </summary> 6 public class ThumbCollection : IList, ICollection, IEnumerable 7 { 8 private ArrayList m_Thumbs;//缩略图 9 private ImageListEx m_Owner;//父ImageListEx 10 private bool m_Disposed;//是否已释放资源 11 12 13 /// <summary> 14 /// 数量 15 /// </summary> 16 public int Count 17 { 18 get 19 { 20 return (this.m_Thumbs == null) ? 0 : this.m_Thumbs.Count; 21 } 22 } 23 24 /// <summary> 25 /// 是否为空 26 /// </summary> 27 public bool Empty 28 { 29 get 30 { 31 return (this.Count == 0); 32 } 33 } 34 35 /// <summary> 36 /// 是否只读 37 /// </summary> 38 public bool IsReadOnly 39 { 40 get 41 { 42 return false; 43 } 44 } 45 46 /// <summary> 47 /// 键集合 48 /// </summary> 49 public StringCollection Keys 50 { 51 get 52 { 53 this.CheckDisposed(); 54 55 StringCollection strings = new StringCollection(); 56 for (int i = 0, length = this.Count; i < length; i++) 57 { 58 ImageInfo imgInfo = this.m_Thumbs[i] as ImageInfo; 59 strings.Add(imgInfo == null ? null : imgInfo.Name); 60 } 61 return strings; 62 } 63 } 64 65 66 /// <summary> 67 /// 构造函数 68 /// </summary> 69 /// <param name="owner">父ImageListEx</param> 70 public ThumbCollection(ImageListEx owner) 71 { 72 this.m_Thumbs = new ArrayList(); 73 this.m_Owner = owner; 74 } 75 76 77 //创建缩略图 78 private ImageInfo CreteThumbInfo(ImageInfo value) 79 { 80 ImageInfo imgInfo = new ImageInfo(); 81 imgInfo.Name = value.Name; 82 if (value != null && this.m_Owner != null) 83 imgInfo.Image = ControlPaintEx.StretchImage(value.Image, this.m_Owner.ImageSize); 84 return imgInfo; 85 } 86 87 //检测是否释放 88 private void CheckDisposed() 89 { 90 if (this.m_Disposed) 91 throw (new ObjectDisposedException("m_Thumbs")); 92 } 93 94 //索引是否在有效范围 95 private bool IsValidIndex(int index) 96 { 97 return ((index >= 0) && (index < this.Count)); 98 } 99 100 101 #region 自身成员 102 103 /// <summary> 104 /// 添加图像信息 105 /// </summary> 106 /// <param name="value">图像信息</param> 107 public void Add(ImageInfo value) 108 { 109 this.CheckDisposed(); 110 this.m_Thumbs.Add(this.CreteThumbInfo(value)); 111 } 112 113 /// <summary> 114 /// 添加图像信息数组 115 /// </summary> 116 /// <param name="values">图像信息数组</param> 117 public void AddRange(ImageInfo[] values) 118 { 119 this.CheckDisposed(); 120 if (values == null) 121 throw new ArgumentNullException("values"); 122 foreach (ImageInfo value in values) 123 this.m_Thumbs.Add(this.CreteThumbInfo(value)); 124 } 125 126 /// <summary> 127 /// 清空所有图像信息并释放其使用的临时资源 128 /// </summary> 129 public void Clear() 130 { 131 if (this.m_Thumbs != null) 132 { 133 for (int i = 0, length = this.Count; i < length; i++) 134 { 135 ImageInfo imgInfo = this.m_Thumbs[i] as ImageInfo; 136 if (imgInfo != null && imgInfo.Image != null) 137 { 138 imgInfo.Image.Dispose(); 139 imgInfo.Image = null; 140 this.m_Thumbs[i] = null; 141 } 142 } 143 this.m_Thumbs.Clear(); 144 } 145 } 146 147 /// <summary> 148 /// 是否包含指定图像信息 149 /// </summary> 150 /// <param name="value">图像信息</param> 151 /// <returns>包含返回true,否则返回false</returns> 152 [EditorBrowsable(EditorBrowsableState.Never)] 153 public bool Contains(ImageInfo value) 154 { 155 throw new NotSupportedException(); 156 } 157 158 /// <summary> 159 /// 是否包含指定key 160 /// </summary> 161 /// <param name="key">键</param> 162 /// <returns>包含返回true,否则返回false</returns> 163 public bool ContainsKey(string key) 164 { 165 return this.IsValidIndex(this.IndexOfKey(key)); 166 } 167 168 /// <summary> 169 /// 释放资源 170 /// </summary> 171 public void Dispose() 172 { 173 if (this.m_Disposed) 174 return; 175 this.m_Disposed = true; 176 177 this.Clear(); 178 this.m_Thumbs = null; 179 } 180 181 /// <summary> 182 /// 获取枚举数 183 /// </summary> 184 /// <returns>枚举数</returns> 185 public IEnumerator GetEnumerator() 186 { 187 this.CheckDisposed(); 188 return this.m_Thumbs.GetEnumerator(); 189 } 190 191 /// <summary> 192 /// 检索指定图像信息 193 /// </summary> 194 /// <param name="value">图像信息</param> 195 /// <returns>图像信息的索引</returns> 196 [EditorBrowsable(EditorBrowsableState.Never)] 197 public int IndexOf(ImageInfo value) 198 { 199 throw new NotSupportedException(); 200 } 201 202 /// <summary> 203 /// 检索指定key 204 /// </summary> 205 /// <param name="key">键</param> 206 /// <returns>键的索引</returns> 207 public int IndexOfKey(string key) 208 { 209 this.CheckDisposed(); 210 for (int i = 0, length = this.Count; i < length; i++) 211 { 212 if ((this.m_Thumbs[i] as ImageInfo).Name == key) 213 return i; 214 } 215 return -1; 216 } 217 218 /// <summary> 219 /// 移除指定图像信息 220 /// </summary> 221 /// <param name="value">图像信息</param> 222 [EditorBrowsable(EditorBrowsableState.Never)] 223 public void Remove(ImageInfo value) 224 { 225 throw new NotSupportedException(); 226 } 227 228 /// <summary> 229 /// 移除指定索引的图像信息 230 /// </summary> 231 /// <param name="index">索引</param> 232 public void RemoveAt(int index) 233 { 234 this.CheckDisposed(); 235 if (this.IsValidIndex(index)) 236 this.m_Thumbs.RemoveAt(index); 237 else 238 throw new ArgumentOutOfRangeException("index"); 239 } 240 241 /// <summary> 242 /// 移除指定key的图像信息 243 /// </summary> 244 /// <param name="key">键</param> 245 public void RemoveByKey(string key) 246 { 247 int index = this.IndexOfKey(key); 248 if (this.IsValidIndex(index)) 249 this.m_Thumbs.RemoveAt(index); 250 } 251 252 /// <summary> 253 /// 设置指定索引的图像信息的key 254 /// </summary> 255 /// <param name="index">索引</param> 256 /// <param name="key">键</param> 257 public void SetKeyName(int index, string key) 258 { 259 this.CheckDisposed(); 260 if (!this.IsValidIndex(index)) 261 throw new IndexOutOfRangeException(); 262 if (this.m_Thumbs[index] == null) 263 this.m_Thumbs[index] = new ImageInfo(); 264 (this.m_Thumbs[index] as ImageInfo).Name = key; 265 } 266 267 /// <summary> 268 /// 获取或设置指定索引的图像信息 269 /// </summary> 270 /// <param name="index">索引</param> 271 /// <returns>图像信息</returns> 272 public ImageInfo this[int index] 273 { 274 get 275 { 276 this.CheckDisposed(); 277 if (!this.IsValidIndex(index)) 278 throw new ArgumentOutOfRangeException("index"); 279 return this.m_Thumbs[index] as ImageInfo; 280 } 281 282 set 283 { 284 this.CheckDisposed(); 285 if (!this.IsValidIndex(index)) 286 throw new ArgumentOutOfRangeException("index"); 287 this.m_Thumbs[index] = this.CreteThumbInfo(value); 288 } 289 } 290 291 /// <summary> 292 /// 获取指定键的图像信息 293 /// </summary> 294 /// <param name="key">键</param> 295 /// <returns>图像信息</returns> 296 public ImageInfo this[string key] 297 { 298 get 299 { 300 this.CheckDisposed(); 301 if ((key != null) && (key.Length > 0)) 302 { 303 int index = this.IndexOfKey(key); 304 if (this.IsValidIndex(index)) 305 return this.m_Thumbs[index] as ImageInfo; 306 } 307 return null; 308 } 309 } 310 311 #endregion 312 313 #region IList 成员 314 315 int IList.Add(object value) 316 { 317 if (!(value is ImageInfo)) 318 { 319 throw new ArgumentException("BadImageInfo", "value"); 320 } 321 this.Add((ImageInfo)value); 322 return (this.Count - 1); 323 324 } 325 326 void IList.Clear() 327 { 328 this.Clear(); 329 } 330 331 bool IList.Contains(object value) 332 { 333 return ((value is ImageInfo) && this.Contains((ImageInfo)value)); 334 335 } 336 337 int IList.IndexOf(object value) 338 { 339 if (value is ImageInfo) 340 return this.IndexOf((ImageInfo)value); 341 return -1; 342 } 343 344 void IList.Insert(int index, object value) 345 { 346 throw new NotSupportedException(); 347 } 348 349 bool IList.IsFixedSize 350 { 351 get { return false; } 352 } 353 354 bool IList.IsReadOnly 355 { 356 get { return this.IsReadOnly; } 357 } 358 359 void IList.Remove(object value) 360 { 361 if (value is ImageInfo) 362 this.Remove((ImageInfo)value); 363 } 364 365 void IList.RemoveAt(int index) 366 { 367 this.RemoveAt(index); 368 } 369 370 object IList.this[int index] 371 { 372 get 373 { 374 return this[index]; 375 } 376 set 377 { 378 if (!(value is ImageInfo)) 379 throw new ArgumentException("BadImageInfo", "value"); 380 this[index] = (ImageInfo)value; 381 } 382 } 383 384 #endregion 385 386 #region ICollection 成员 387 388 void ICollection.CopyTo(Array array, int index) 389 { 390 for (int i = 0, length = this.Count; i < length; i++) 391 array.SetValue(this.m_Thumbs[i], index++); 392 } 393 394 int ICollection.Count 395 { 396 get { return this.Count; } 397 } 398 399 bool ICollection.IsSynchronized 400 { 401 get { return false; } 402 } 403 404 object ICollection.SyncRoot 405 { 406 get { return this; } 407 } 408 409 #endregion 410 411 #region IEnumerable 成员 412 413 IEnumerator IEnumerable.GetEnumerator() 414 { 415 return this.GetEnumerator(); 416 } 417 418 #endregion 419 } 420 }
附图:
通过对比可以明显的发现ImageList的alpha通道bug。红框内为ImageList的图像绘制后的效果,其他的图标为ImageLisEx的图像绘制后的效果。