上午刚写了一篇关于带ToolTip的ListBox控件,这一篇是针对所有项,无论项文本长度有无超出控件,都会呈现ToolTip。现在这一篇基础上加一些限制并引进图标显示,只对超出部分的项才呈现ToolTip,项文本对超出部分用“...”替代
详见代码:
一、自定义项
/// <summary>
/// 自定义项
/// </summary>
class MyListBoxItem : IDisposable
{
private string _txt;
private Image _img;
/// <summary>
/// 项文本
/// </summary>
public string Text
{
get { return _txt; }
set { _txt = value; }
}
/// <summary>
/// 项图标(可为null)
/// </summary>
public Image ItemImage
{
get { return _img; }
set { _img = value; }
}
/// <summary>
/// 是否显示tooltip
/// </summary>
public bool ShowTip { get; set; }
/// <summary>
/// 带图标构造函数
/// </summary>
/// <param name="txt"></param>
/// <param name="img"></param>
public MyListBoxItem(string txt, Image img)
{
_txt = txt;
_img = img;
}
/// <summary>
/// 不带图标构造函数
/// </summary>
/// <param name="txt"></param>
public MyListBoxItem(string txt)
{
_txt = txt;
}
/// <summary>
/// 重写ToString获取项文本
/// </summary>
/// <returns></returns>
public override string ToString()
{
return _txt;
}
public void Dispose()
{
_img = null;
}
}
二、编写MyListBox,继承ListBox
class MyListBox : ListBox
{
/// <summary>
/// 是否带图标
/// </summary>
private bool HasIcon { get; set; }
/// <summary>
/// 图标宽度(仅在HasIcon属性为true时有效)
/// </summary>
private int IconWidth { get; set; }
/// <summary>
/// 图标高度(仅在HasIcon属性为true时有效)
/// </summary>
private int IconHeight { get; set; }
ToolTip tip = new ToolTip();
public MyListBox()
{
this.DrawMode = DrawMode.OwnerDrawFixed;
}
/// <summary>
/// 设置图标大小(若不带图标就无需设置)
/// </summary>
/// <param name="w">图标宽度</param>
/// <param name="h">图标高度</param>
public void SetIconSize(int w, int h)
{
this.HasIcon = true;
this.IconWidth = w;
this.IconHeight = h;
this.ItemHeight = h;
}
protected override void OnDrawItem(DrawItemEventArgs e)
{
e.DrawBackground();
e.DrawFocusRectangle();
Graphics g = e.Graphics;
StringFormat sf = new StringFormat();
sf.Trimming = StringTrimming.EllipsisCharacter; //超出指定矩形区域部分用"..."替代
sf.LineAlignment = StringAlignment.Center;//垂直居中
try
{
MyListBoxItem item = (MyListBoxItem)Items[e.Index];
SizeF size = g.MeasureString(item.Text, e.Font); //获取项文本尺寸
if (HasIcon) //带图标时
{
if (size.Width > e.Bounds.Width - this.IconWidth) //项文本宽度超过 项宽-图标宽度
{
item.ShowTip = true; //显示tooltip
}
/* 获取指定矩形区域,注意不能直接用项所在矩形,否则DrawString时会出现自动换行
* 的情况。前面说超出指定矩形区域用“...”替代 指的是DrawString方法会先塞满整个
* 矩形区域,如果区域高度够时,就会出现自动换行的情况 ******/
RectangleF rectF = new RectangleF(e.Bounds.Left,
e.Index * this.ItemHeight + (this.ItemHeight - size.Height) / 2.0f,
e.Bounds.Width - this.IconWidth, size.Height);
//写 项文本
g.DrawString(item.Text, e.Font, new SolidBrush(e.ForeColor), rectF, sf);
if (item.ItemImage != null) //在项右侧 画图标
{
/* 注意不能用DrawImage(img, x, y)方法,务必指定图标的大小,
* 否则会导致图标被放大,读者不妨一试 :) *****/
g.DrawImage(item.ItemImage, e.Bounds.Right - this.IconWidth, e.Bounds.Top, this.IconWidth, this.IconHeight);
}
}
else //不带图标
{
if (size.Width > e.Bounds.Width) //项文本宽度超过 项宽
{
item.ShowTip = true; //显示tooltip
}
//获取指定矩形区域
RectangleF rectF = new RectangleF(e.Bounds.Left,
e.Index * this.ItemHeight + (this.ItemHeight - size.Height) / 2.0f,
e.Bounds.Width, size.Height);
//写 项文本
g.DrawString(item.Text, e.Font, new SolidBrush(e.ForeColor), rectF, sf);
}
}
catch { } //忽略异常
base.OnDrawItem(e);
}
/// <summary>
/// 重写鼠标移动事件
/// </summary>
/// <param name="e"></param>
protected override void OnMouseMove(MouseEventArgs e)
{
base.OnMouseMove(e);
int idx = IndexFromPoint(e.Location); //获取鼠标所在的项索引
if (idx == MyListBox.NoMatches) //鼠标所在位置没有 项
{
tip.SetToolTip(this, ""); //设置提示信息为空
}
else
{
MyListBoxItem item = (MyListBoxItem)this.Items[idx];
if (item.ShowTip)
{
string txt = this.Items[idx].ToString(); //获取项文本
tip.SetToolTip(this, txt); //设置提示信息
}
else
{
tip.SetToolTip(this, ""); //设置提示信息为空
}
}
}
}
三、实例
public Form1()
{
InitializeComponent();
//myListBox1--带图标
myListBox1.SetIconSize(32, 32);
Image img = Image.FromFile(@"C:\Documents and Settings\Administrator\桌面\Ques.png");
MyListBoxItem i1 = new MyListBoxItem("dfd dfd f", img);
myListBox1.Items.Add(i1);
i1 = new MyListBoxItem("dfd dfd f d df df dfdfd fd", img);
myListBox1.Items.Add(i1);
i1 = new MyListBoxItem("dfd dfd f", null);
myListBox1.Items.Add(i1);
//myListBox2--不带图标
i1 = new MyListBoxItem("dfd dfd f");
myListBox2.Items.Add(i1);
i1 = new MyListBoxItem("dfd dfd f d df df dfdfd fd");
myListBox2.Items.Add(i1);
i1 = new MyListBoxItem("d");
myListBox2.Items.Add(i1);
}
四、效果