winform下重画ListBox

Posted belx

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了winform下重画ListBox相关的知识,希望对你有一定的参考价值。

原文https://www.cnblogs.com/yuefei/p/4062998.html

技术分享图片

修改

自定义控件

using System;
using System.Collections;
using System.ComponentModel;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Windows.Forms;
using winform下重画ListBox.Properties;

namespace winform下重画ListBox
{
    public partial class UserListBox : ListBox
    {
        private readonly ListBoxItemCollection m_Items;
        public ListBoxItem mouseItem;

        public UserListBox()
        {
            InitializeComponent();

            m_Items = new ListBoxItemCollection(this);

            base.DrawMode = DrawMode.OwnerDrawVariable;
            SetStyle(ControlStyles.UserPaint, true);
            SetStyle(ControlStyles.DoubleBuffer, true); // 双缓冲
            SetStyle(ControlStyles.OptimizedDoubleBuffer, true); // 双缓冲   
            SetStyle(ControlStyles.ResizeRedraw, true); // 调整大小时重绘
            SetStyle(ControlStyles.AllPaintingInWmPaint, true); // 禁止擦除背景. 
            SetStyle(ControlStyles.SupportsTransparentBackColor, true); // 开启控件透明
        }

        public new ListBoxItemCollection Items
        {
            get { return m_Items; }
        }

        internal ObjectCollection OldItemSource
        {
            get { return base.Items; }
        }

        protected override void OnPaint(PaintEventArgs e)
        {
            Graphics g = e.Graphics;

            // you can set SeletedItem background
            if (Focused && SelectedItem != null)
            {
            }

            for (int i = 0; i < Items.Count; i++)
            {
                Rectangle bounds = GetItemRectangle(i);

                if (mouseItem == Items[i])
                {
                    Color leftColor = Color.FromArgb(200, 192, 224, 248);
                    using (var brush = new SolidBrush(leftColor))
                    {
                        g.FillRectangle(brush, new Rectangle(bounds.X, bounds.Y, bounds.Width, bounds.Height));
                    }

                    Color rightColor = Color.FromArgb(252, 233, 161);
                    using (var brush = new SolidBrush(rightColor))
                    {
                        g.FillRectangle(brush, new Rectangle(bounds.Width - 40, bounds.Y, 40, bounds.Height));
                    }
                }

                int fontLeft = bounds.Left + 40 + 15;
                var font = new Font("微软雅黑", 9);
                g.DrawString(Items[i].Name, font, new SolidBrush(ForeColor), fontLeft, bounds.Top + 5);
                g.DrawString(Items[i].IP, font, new SolidBrush(Color.FromArgb(128, 128, 128)), fontLeft, bounds.Top + 20);
                g.DrawString(Items[i].Mac, font, new SolidBrush(Color.FromArgb(128, 128, 128)), fontLeft,
                             bounds.Top + 35);

                if (Items[i].Image != null)
                {
                    g.InterpolationMode = InterpolationMode.HighQualityBilinear;
                    g.DrawImage(Items[i].Image, new Rectangle(bounds.X + 5, (bounds.Height - 40)/2 + bounds.Top, 40, 40));
                }
                g.DrawImage(Resources.delete,
                            new Rectangle(bounds.Width - 28, (bounds.Height - 16)/2 + bounds.Top, 16, 16));
            }
            base.OnPaint(e);
        }

        protected override void OnMeasureItem(MeasureItemEventArgs e)
        {
            base.OnMeasureItem(e);
            if (Items.Count > 0)
            {
                ListBoxItem item = Items[e.Index];
                e.ItemHeight = 54;
            }
        }

        protected override void OnMouseMove(MouseEventArgs e)
        {
            base.OnMouseMove(e);
            for (int i = 0; i < Items.Count; i++)
            {
                Rectangle bounds = GetItemRectangle(i);
                var deleteBounds = new Rectangle(bounds.Width - 28, (bounds.Height - 16)/2 + bounds.Top, 16, 16);
                if (bounds.Contains(e.X, e.Y))
                {
                    if (Items[i] != mouseItem)
                    {
                        mouseItem = Items[i];
                    }

                    if (deleteBounds.Contains(e.X, e.Y))
                    {
                        mouseItem.IsFocus = true;
                        Cursor = Cursors.Hand;
                    }
                    else
                    {
                        mouseItem.IsFocus = false;
                        Cursor = Cursors.Arrow;
                    }

                    Invalidate();
                    break;
                }
            }
        }

        protected override void OnMouseClick(MouseEventArgs e)
        {
            base.OnMouseClick(e);
            if (mouseItem.IsFocus)
            {
                ListBoxItem deleteItem = mouseItem;
                if (MessageBox.Show("confirm to delete", "", MessageBoxButtons.OKCancel) == DialogResult.OK)
                {
                    Items.Remove(deleteItem);
                }
            }
        }

        protected override void OnMouseLeave(EventArgs e)
        {
            base.OnMouseLeave(e);
            mouseItem = null;
            Invalidate();
        }
    }

    //首先我们设计一个承载数据的类ListBoxItem。
    public class ListBoxItem : IDisposable
    {
        public ListBoxItem()
        {
        }

        public ListBoxItem(Guid id, string name, string ip, string mac, Image image)
        {
            Id = id;
            Name = name;
            IP = ip;
            Mac = mac;
            Image = image;
            IsFocus = false;
        }

        public Guid Id { get; set; }

        public string Name { get; set; }

        public string IP { get; set; }

        public string Mac { get; set; }

        [DefaultValue(typeof (Image), "null")]
        public Image Image { get; set; }

        public bool IsFocus { get; set; }

        public void Dispose()
        {
            Image = null;
        }
    }

    //然后我们再为ListBox写一个用于展现数据的数据源ListBoxItemCollection,这里实现了迭代和集合操作接口,可以根据需要扩展数据操作方法。
    [ListBindable(false)]
    public class ListBoxItemCollection : IList, ICollection, IEnumerable
    {
        private readonly UserListBox m_owner;

        public ListBoxItemCollection(UserListBox owner)
        {
            m_owner = owner;
        }

        internal UserListBox Owner
        {
            get { return m_owner; }
        }

        #region  override

        public ListBoxItem this[int index]
        {
            get { return Owner.OldItemSource[index] as ListBoxItem; }
            set { Owner.OldItemSource[index] = value; }
        }

        public int Count
        {
            get { return Owner.OldItemSource.Count; }
        }

        public bool IsReadOnly
        {
            get { return Owner.OldItemSource.IsReadOnly; }
        }

        int IList.Add(object value)
        {
            if (!(value is ListBoxItem))
            {
                throw new ArgumentException();
            }
            return Add(value as ListBoxItem);
        }

        void IList.Clear()
        {
            Clear();
        }

        bool IList.Contains(object value)
        {
            return Contains(value as ListBoxItem);
        }

        int IList.IndexOf(object value)
        {
            return IndexOf(value as ListBoxItem);
        }

        void IList.Insert(int index, object value)
        {
            if (!(value is ListBoxItem))
            {
                throw new ArgumentException();
            }
            Insert(index, value as ListBoxItem);
        }

        bool IList.IsFixedSize
        {
            get { return false; }
        }

        bool IList.IsReadOnly
        {
            get { return IsReadOnly; }
        }

        void IList.Remove(object value)
        {
            Remove(value as ListBoxItem);
        }

        void IList.RemoveAt(int index)
        {
            RemoveAt(index);
        }

        object IList.this[int index]
        {
            get { return this[index]; }
            set
            {
                if (!(value is ListBoxItem))
                {
                    throw new ArgumentException();
                }
                this[index] = value as ListBoxItem;
            }
        }

        void ICollection.CopyTo(Array array, int index)
        {
            CopyTo((ListBoxItem[]) array, index);
        }

        int ICollection.Count
        {
            get { return Count; }
        }

        bool ICollection.IsSynchronized
        {
            get { return false; }
        }

        object ICollection.SyncRoot
        {
            get { return false; }
        }

        IEnumerator IEnumerable.GetEnumerator()
        {
            return GetEnumerator();
        }

        public int Add(ListBoxItem item)
        {
            if (item == null)
            {
                throw new ArgumentException("item is null");
            }
            return Owner.OldItemSource.Add(item);
        }

        public void AddRange(ListBoxItem[] items)
        {
            Owner.OldItemSource.AddRange(items);
        }

        public void Clear()
        {
            if (Owner.OldItemSource.Count > 0)
            {
                Owner.OldItemSource.Clear();
            }
        }

        public bool Contains(ListBoxItem item)
        {
            bool rst = false;
            foreach (ListBoxItem oldItem in Owner.OldItemSource)
            {
                if (oldItem.Id == item.Id)
                {
                    rst = true;
                    break;
                }
            }
            return rst;
        }

        public void CopyTo(ListBoxItem[] destination, int arrayIndex)
        {
            Owner.OldItemSource.CopyTo(destination, arrayIndex);
        }

        public int IndexOf(ListBoxItem item)
        {
            return Owner.OldItemSource.IndexOf(item);
        }

        public void Insert(int index, ListBoxItem item)
        {
            if (item == null)
            {
                throw new ArgumentException("item is null");
            }
            Owner.OldItemSource.Insert(index, item);
        }

        public void Remove(ListBoxItem item)
        {
            Owner.OldItemSource.Remove(item);
        }

        public void RemoveAt(int index)
        {
            Owner.OldItemSource.RemoveAt(index);
        }

        public IEnumerator GetEnumerator()
        {
            return Owner.OldItemSource.GetEnumerator();
        }

        #endregion

        #region  extention

        public ListBoxItem FindByMac(string mac)
        {
            foreach (ListBoxItem item in Owner.OldItemSource)
            {
                if (item.Mac == mac)
                {
                    return item;
                }
            }
            return null;
        }

        #endregion
    }
}

测试

using System;
using System.Windows.Forms;
using winform下重画ListBox.Properties;

namespace winform下重画ListBox
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            //ListBoxItem(Guid id, string name, string ip, string mac, Image image)
            listBox1.Items.Add(new ListBoxItem(Guid.NewGuid(), "Name", "192.168.0.1", "Mac", Resources.delete));
            listBox1.Items.Add(new ListBoxItem(Guid.NewGuid(), "Name", "192.168.0.1", "Mac", Resources.delete));
        }
    }
}

 

以上是关于winform下重画ListBox的主要内容,如果未能解决你的问题,请参考以下文章

winform listbox增加鼠标双击事件

WinForm ListBox - 如何显示对象中的文本?

winform中的listbox怎样添加双击事件

winform中的listbox怎样添加双击事件

如何在 WinForms 中将字典绑定到 ListBox

程序不会让我以任何方式清除我的 listBox [C#, WinForms]