由于ImageList的先天障碍,对alpha通道支持不好。虽然到xp有所改善,但瑕疵依然存在。

通过reflactor发现ImageList通过windows api来进行读写的。写入数据时会对原始图像进行处理,等到读取时已经获取不到原始图像。鉴于此,只能另起炉灶重新编写一个ImageList,也就是缩略图集合类。

思路:

1,应该有缩略图大小属性,由于添加图像后生成缩略图,并与原始图像断绝关系。所以在有缩略图的情况下不允许修改大小。

2,缩略图集合。可增加图像到集合,添加时按指定大小生成缩略图。可通过索引检索以便调用。删除或清空时要释放生成的资源。

好了,以上就是主题思想。下面是代码。

ImageListEx类代码

     /// <summary>
/// 缩略图集合
/// </summary>
public sealed partial class ImageListEx : Component
{
private object m_Tag;
/// <summary>
/// 附加数据
/// </summary>
[DefaultValue(null), TypeConverter(typeof(StringConverter))]
public object Tag
{
get
{
return this.m_Tag;
}
set
{
this.m_Tag = value;
}
} private Size m_Size = new Size(, );
/// <summary>
/// 缩略图大小,只能先设置大小后添加图片
/// </summary>
[DefaultValue(typeof(Size), "32,32")]
public Size ImageSize
{
get
{
return this.m_Size;
} set
{
if (value.Width <= || value.Height <= || this.ImageThumbs.Count > )
return; this.m_Size = value;
}
} private ThumbCollection m_ImageThumbs;
/// <summary>
/// 缩略图,只能先设置大小后添加图片
/// </summary>
[DefaultValue(null), DesignerSerializationVisibility(DesignerSerializationVisibility.Content), MergableProperty(false)]
public ThumbCollection ImageThumbs
{
get
{
if (this.m_ImageThumbs == null)
this.m_ImageThumbs = new ThumbCollection(this); return this.m_ImageThumbs;
}
} /// <summary>
/// 构造函数
/// </summary>
public ImageListEx()
{
} /// <summary>
/// 构造函数
/// </summary>
/// <param name="container">容器</param>
public ImageListEx(IContainer container)
{
container.Add(this);
} /// <summary>
/// 转换为字符串
/// </summary>
/// <returns>字符串</returns>
public override string ToString()
{
string str = base.ToString();
if (this.m_ImageThumbs != null)
{
return (str + " ImageThumbs.Count: " + this.m_ImageThumbs.Count.ToString(CultureInfo.CurrentCulture) + ", ImageSize: " + this.ImageSize.ToString());
}
return str;
} /// <summary>
/// 清理所有正在使用的资源。
/// </summary>
/// <param name="disposing">如果应释放托管资源,为 true;否则为 false。</param>
protected override void Dispose(bool disposing)
{
if (this.m_ImageThumbs != null)
this.m_ImageThumbs.Dispose(); base.Dispose(disposing);
}
}

ImageListEx.ImageInfo类代码

     public partial class ImageListEx
{
/// <summary>
/// 图像信息
/// </summary>
public class ImageInfo
{
private string m_Name;
/// <summary>
/// 名称说明
/// </summary>
[DefaultValue(null)]
public string Name
{
get
{
return this.m_Name;
} set
{
this.m_Name = value;
}
} private Image m_Image;
/// <summary>
/// 图像
/// </summary>
[DefaultValue(null)]
public Image Image
{
get
{
return this.m_Image;
} set
{
this.m_Image = value;
}
} /// <summary>
/// 构造函数
/// </summary>
public ImageInfo()
{
} /// <summary>
/// 构造函数
/// </summary>
/// <param name="name">名称说明</param>
/// <param name="image">图像</param>
public ImageInfo(string name, Image image)
{
this.m_Name = name;
this.m_Image = image;
}
}
}

ImageListEx.ThumbCollection类代码

     public partial class ImageListEx
{
/// <summary>
/// 缩略图集合
/// </summary>
public class ThumbCollection : IList, ICollection, IEnumerable
{
private ArrayList m_Thumbs;//缩略图
private ImageListEx m_Owner;//父ImageListEx
private bool m_Disposed;//是否已释放资源 /// <summary>
/// 数量
/// </summary>
public int Count
{
get
{
return (this.m_Thumbs == null) ? : this.m_Thumbs.Count;
}
} /// <summary>
/// 是否为空
/// </summary>
public bool Empty
{
get
{
return (this.Count == );
}
} /// <summary>
/// 是否只读
/// </summary>
public bool IsReadOnly
{
get
{
return false;
}
} /// <summary>
/// 键集合
/// </summary>
public StringCollection Keys
{
get
{
this.CheckDisposed(); StringCollection strings = new StringCollection();
for (int i = , length = this.Count; i < length; i++)
{
ImageInfo imgInfo = this.m_Thumbs[i] as ImageInfo;
strings.Add(imgInfo == null ? null : imgInfo.Name);
}
return strings;
}
} /// <summary>
/// 构造函数
/// </summary>
/// <param name="owner">父ImageListEx</param>
public ThumbCollection(ImageListEx owner)
{
this.m_Thumbs = new ArrayList();
this.m_Owner = owner;
} //创建缩略图
private ImageInfo CreteThumbInfo(ImageInfo value)
{
ImageInfo imgInfo = new ImageInfo();
imgInfo.Name = value.Name;
if (value != null && this.m_Owner != null)
imgInfo.Image = ControlPaintEx.StretchImage(value.Image, this.m_Owner.ImageSize);
return imgInfo;
} //检测是否释放
private void CheckDisposed()
{
if (this.m_Disposed)
throw (new ObjectDisposedException("m_Thumbs"));
} //索引是否在有效范围
private bool IsValidIndex(int index)
{
return ((index >= ) && (index < this.Count));
} #region 自身成员 /// <summary>
/// 添加图像信息
/// </summary>
/// <param name="value">图像信息</param>
public void Add(ImageInfo value)
{
this.CheckDisposed();
this.m_Thumbs.Add(this.CreteThumbInfo(value));
} /// <summary>
/// 添加图像信息数组
/// </summary>
/// <param name="values">图像信息数组</param>
public void AddRange(ImageInfo[] values)
{
this.CheckDisposed();
if (values == null)
throw new ArgumentNullException("values");
foreach (ImageInfo value in values)
this.m_Thumbs.Add(this.CreteThumbInfo(value));
} /// <summary>
/// 清空所有图像信息并释放其使用的临时资源
/// </summary>
public void Clear()
{
if (this.m_Thumbs != null)
{
for (int i = , length = this.Count; i < length; i++)
{
ImageInfo imgInfo = this.m_Thumbs[i] as ImageInfo;
if (imgInfo != null && imgInfo.Image != null)
{
imgInfo.Image.Dispose();
imgInfo.Image = null;
this.m_Thumbs[i] = null;
}
}
this.m_Thumbs.Clear();
}
} /// <summary>
/// 是否包含指定图像信息
/// </summary>
/// <param name="value">图像信息</param>
/// <returns>包含返回true,否则返回false</returns>
[EditorBrowsable(EditorBrowsableState.Never)]
public bool Contains(ImageInfo value)
{
throw new NotSupportedException();
} /// <summary>
/// 是否包含指定key
/// </summary>
/// <param name="key">键</param>
/// <returns>包含返回true,否则返回false</returns>
public bool ContainsKey(string key)
{
return this.IsValidIndex(this.IndexOfKey(key));
} /// <summary>
/// 释放资源
/// </summary>
public void Dispose()
{
if (this.m_Disposed)
return;
this.m_Disposed = true; this.Clear();
this.m_Thumbs = null;
} /// <summary>
/// 获取枚举数
/// </summary>
/// <returns>枚举数</returns>
public IEnumerator GetEnumerator()
{
this.CheckDisposed();
return this.m_Thumbs.GetEnumerator();
} /// <summary>
/// 检索指定图像信息
/// </summary>
/// <param name="value">图像信息</param>
/// <returns>图像信息的索引</returns>
[EditorBrowsable(EditorBrowsableState.Never)]
public int IndexOf(ImageInfo value)
{
throw new NotSupportedException();
} /// <summary>
/// 检索指定key
/// </summary>
/// <param name="key">键</param>
/// <returns>键的索引</returns>
public int IndexOfKey(string key)
{
this.CheckDisposed();
for (int i = , length = this.Count; i < length; i++)
{
if ((this.m_Thumbs[i] as ImageInfo).Name == key)
return i;
}
return -;
} /// <summary>
/// 移除指定图像信息
/// </summary>
/// <param name="value">图像信息</param>
[EditorBrowsable(EditorBrowsableState.Never)]
public void Remove(ImageInfo value)
{
throw new NotSupportedException();
} /// <summary>
/// 移除指定索引的图像信息
/// </summary>
/// <param name="index">索引</param>
public void RemoveAt(int index)
{
this.CheckDisposed();
if (this.IsValidIndex(index))
this.m_Thumbs.RemoveAt(index);
else
throw new ArgumentOutOfRangeException("index");
} /// <summary>
/// 移除指定key的图像信息
/// </summary>
/// <param name="key">键</param>
public void RemoveByKey(string key)
{
int index = this.IndexOfKey(key);
if (this.IsValidIndex(index))
this.m_Thumbs.RemoveAt(index);
} /// <summary>
/// 设置指定索引的图像信息的key
/// </summary>
/// <param name="index">索引</param>
/// <param name="key">键</param>
public void SetKeyName(int index, string key)
{
this.CheckDisposed();
if (!this.IsValidIndex(index))
throw new IndexOutOfRangeException();
if (this.m_Thumbs[index] == null)
this.m_Thumbs[index] = new ImageInfo();
(this.m_Thumbs[index] as ImageInfo).Name = key;
} /// <summary>
/// 获取或设置指定索引的图像信息
/// </summary>
/// <param name="index">索引</param>
/// <returns>图像信息</returns>
public ImageInfo this[int index]
{
get
{
this.CheckDisposed();
if (!this.IsValidIndex(index))
throw new ArgumentOutOfRangeException("index");
return this.m_Thumbs[index] as ImageInfo;
} set
{
this.CheckDisposed();
if (!this.IsValidIndex(index))
throw new ArgumentOutOfRangeException("index");
this.m_Thumbs[index] = this.CreteThumbInfo(value);
}
} /// <summary>
/// 获取指定键的图像信息
/// </summary>
/// <param name="key">键</param>
/// <returns>图像信息</returns>
public ImageInfo this[string key]
{
get
{
this.CheckDisposed();
if ((key != null) && (key.Length > ))
{
int index = this.IndexOfKey(key);
if (this.IsValidIndex(index))
return this.m_Thumbs[index] as ImageInfo;
}
return null;
}
} #endregion #region IList 成员 int IList.Add(object value)
{
if (!(value is ImageInfo))
{
throw new ArgumentException("BadImageInfo", "value");
}
this.Add((ImageInfo)value);
return (this.Count - ); } void IList.Clear()
{
this.Clear();
} bool IList.Contains(object value)
{
return ((value is ImageInfo) && this.Contains((ImageInfo)value)); } int IList.IndexOf(object value)
{
if (value is ImageInfo)
return this.IndexOf((ImageInfo)value);
return -;
} void IList.Insert(int index, object value)
{
throw new NotSupportedException();
} bool IList.IsFixedSize
{
get { return false; }
} bool IList.IsReadOnly
{
get { return this.IsReadOnly; }
} void IList.Remove(object value)
{
if (value is ImageInfo)
this.Remove((ImageInfo)value);
} void IList.RemoveAt(int index)
{
this.RemoveAt(index);
} object IList.this[int index]
{
get
{
return this[index];
}
set
{
if (!(value is ImageInfo))
throw new ArgumentException("BadImageInfo", "value");
this[index] = (ImageInfo)value;
}
} #endregion #region ICollection 成员 void ICollection.CopyTo(Array array, int index)
{
for (int i = , length = this.Count; i < length; i++)
array.SetValue(this.m_Thumbs[i], index++);
} int ICollection.Count
{
get { return this.Count; }
} bool ICollection.IsSynchronized
{
get { return false; }
} object ICollection.SyncRoot
{
get { return this; }
} #endregion #region IEnumerable 成员 IEnumerator IEnumerable.GetEnumerator()
{
return this.GetEnumerator();
} #endregion
}
}

附图:

通过对比可以明显的发现ImageList的alpha通道bug。红框内为ImageList的图像绘制后的效果,其他的图标为ImageLisEx的图像绘制后的效果。

ImageList半透明,Alpha通道bug处理。-LMLPHP

05-02 00:54