C# 编写带图标和tooltip的ListBox

上午刚写了一篇关于带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);
        }


四、效果

  • 0
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 13
    评论
评论 13
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值