【C#】自定义容器控件,设置界面控件,支持设计器拖入控件

先上效果图:

1、先重写设置界面的控件功能:

    public partial class SetterControl : UserControl
    {
        public SetterControl()
        {
            InitializeComponent();
            Initialize();
        }
        /// <summary>
        /// 获取或设置组列表
        /// </summary>
        public Dictionary<string, List<SetterStrip>> Items;
        /// <summary>
        /// 容器
        /// </summary>
        public Panel ItemContainer
        { get; set; }
        ///// <summary>
        ///// 加载
        ///// </summary>
        ///// <param name="e"></param>
        //protected override void OnLoad(EventArgs e)
        //{
        //    base.OnLoad(e);
        //}
        /// <summary>
        /// 鼠标按下
        /// </summary>
        /// <param name="e"></param>
        protected override void OnMouseDown(MouseEventArgs e)
        {
            base.OnMouseDown(e);
            this.Invalidate();
        }
        /// <summary>
        /// 鼠标移动
        /// </summary>
        /// <param name="e"></param>
        protected override void OnMouseMove(MouseEventArgs e)
        {
            base.OnMouseMove(e);
            this.Invalidate();
        }
        /// <summary>
        /// 鼠标弹起
        /// </summary>
        /// <param name="e"></param>
        protected override void OnMouseUp(MouseEventArgs e)
        {
            base.OnMouseUp(e);
            if (Items == null) return;
            int index = 0;
            Point p = new Point(e.X, e.Y);
            foreach (var v in Items)
            {
                Rectangle rect = new Rectangle(_itemW * index, 0, _itemW, _itemH);
                if (rect.Contains(p))
                {
                    _titleIndex = index;
                    _itemIndex = 0;
                    break;
                }
                if (_titleIndex == index)
                {
                    int i = 0;
                    foreach (var item in v.Value)
                    {
                        rect = new Rectangle(0, i * (_itemH - 10) + _itemH, _itemW, (_itemH - 10));
                        if (rect.Contains(p))
                        {
                            _itemIndex = i;
                            if (ItemContainer != null && item.LocationControl != null)
                                ItemContainer.ScrollControlIntoView(item.LocationControl);
                            break;
                        }
                        i++;
                    }
                }
                index++;
            }
            this.Invalidate();
        }
        /// <summary>
        /// 绘制
        /// </summary>
        /// <param name="e"></param>
        protected override void OnPaint(PaintEventArgs e)
        {
            base.OnPaint(e);
            Brush brush = new SolidBrush(Color.FromArgb(238, 238, 238));
            e.Graphics.FillRectangle(brush, new Rectangle(0, 0, this.Width, _itemH));
            e.Graphics.FillRectangle(brush, new Rectangle(0, 0, _itemW, this.Height));
            if (Items != null)
            {
                Point p = this.PointToClient(Control.MousePosition);
                StringFormat sf = new StringFormat()
                {
                    LineAlignment = StringAlignment.Center
                };
                int index = 0;
                foreach (var v in Items)
                {
                    Rectangle rect = new Rectangle(_itemW * index, 0, _itemW, _itemH);
                    Brush b = index == _titleIndex ? Brushes.BlueViolet : rect.Contains(p) ? Brushes.Gold : Brushes.Black;
                    if (index == 0) rect.Offset(20, 0);
                    e.Graphics.DrawString(v.Key, this.Font, b, rect, sf);
                    if (index == _titleIndex)
                    {
                        int i = 0;
                        foreach (var item in v.Value)
                        {
                            rect = new Rectangle(0, i * (_itemH - 10) + _itemH, _itemW, (_itemH - 10));
                            b = i == _itemIndex ? Brushes.White : rect.Contains(p) ? Brushes.LightGray : brush;
                            e.Graphics.FillRectangle(b, rect);
                            rect.Offset(20, 0);
                            e.Graphics.DrawString(item.Name, this.Font, Brushes.Black, rect, sf);
                            i++;
                        }
                    }
                    index++;
                }
            }
            e.Graphics.DrawLine(Pens.Gray, new Point(0, _itemH), new Point(this.Width, _itemH));
            brush.Dispose();
        }

        /// <summary>
        /// 初始化
        /// </summary>
        private void Initialize()
        {
            this.SetStyle(ControlStyles.AllPaintingInWmPaint | ControlStyles.OptimizedDoubleBuffer, true);
        }
        
        private const int _itemH = 50;
        private const int _itemW = 130;
        private int _titleIndex;
        private int _itemIndex;
    }
    [Serializable]
    public class SetterStrip
    {
        /// <summary>
        /// 组名
        /// </summary>
        public string Name
        { get; set; }
        /// <summary>
        /// 组控件坐标
        /// </summary>
        public Control LocationControl
        { get; set; }
    }

2、实现设计器上直接拖入控件功能

    [Designer(typeof(LDesigner))]
    [DesignTimeVisible(true)]
    public class MenuControlEx : SetterControl
    {
        public MenuControlEx()
        {
            InitializeComponent();
        }
        /// <summary>
        /// 获取存放控件的Panel
        /// </summary> 
        [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
        public Panel MenuPanel
        { get { return setterPanel; } }

        private void InitializeComponent()
        {
            this.setterPanel = new System.Windows.Forms.Panel();
            this.SuspendLayout();
            // 
            // setterPanel
            // 
            this.setterPanel.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) 
            | System.Windows.Forms.AnchorStyles.Left) 
            | System.Windows.Forms.AnchorStyles.Right)));
            this.setterPanel.AutoScroll = true;
            this.setterPanel.Location = new System.Drawing.Point(131, 52);
            this.setterPanel.Name = "setterPanel";
            this.setterPanel.Size = new System.Drawing.Size(475, 499);
            this.setterPanel.TabIndex = 0;
            // 
            // MenuControlEx
            // 
            this.Controls.Add(this.setterPanel);
            this.ItemContainer = this.setterPanel;
            this.Name = "MenuControlEx";
            this.ResumeLayout(false);

        }
        private System.Windows.Forms.Panel setterPanel;
    }


    public class LDesigner : ParentControlDesigner
    {
        private MenuControlEx _control;

        public override void Initialize(IComponent component)
        {
            base.Initialize(component);
            _control = (MenuControlEx)component;
            bool succ = this.EnableDesignMode(_control.MenuPanel, "setterPanel");
            if (!succ)
                throw new Exception("加载控件失败");
        }
    }

3、使用方法:

Dictionary<string, List<DLL.Controls.SetterStrip>> items = new Dictionary<string, List<DLL.Controls.SetterStrip>>();
            items.Add("基础设置", new List<DLL.Controls.SetterStrip>() { 
new DLL.Controls.SetterStrip() {Name="常规", LocationControl=button1 },
 new DLL.Controls.SetterStrip() { Name = "快捷键", LocationControl = button2 },
 new DLL.Controls.SetterStrip() { Name = "显示", LocationControl = button3 } 
});
            items.Add("安全设置", new List<DLL.Controls.SetterStrip>() { 
new DLL.Controls.SetterStrip() { Name = "安全1", LocationControl = button1 },
 new DLL.Controls.SetterStrip() { Name = "安全2", LocationControl = button2 }, 
new DLL.Controls.SetterStrip() { Name = "安全3", LocationControl = button3 } 
});
menuControlEx1.Items = items;
//Name是显示的,LocationControl是用来点击按钮,控制滚动条定位的

2018/7/15 补上测试工程

源码下载 

PS. 如果是DLL方式使用,引用该DLL的地方也要引用 System.Design,否则会报错

如果需要技术交流的,可以关注微信公众号:梦琪动漫屋 

原文地址:https://www.cnblogs.com/mqxs/p/8691817.html