先上效果图:

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 = ;
Point p = new Point(e.X, e.Y);
foreach (var v in Items)
{
Rectangle rect = new Rectangle(_itemW * index, , _itemW, _itemH);
if (rect.Contains(p))
{
_titleIndex = index;
_itemIndex = ;
break;
}
if (_titleIndex == index)
{
int i = ;
foreach (var item in v.Value)
{
rect = new Rectangle(, i * (_itemH - ) + _itemH, _itemW, (_itemH - ));
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(, , ));
e.Graphics.FillRectangle(brush, new Rectangle(, , this.Width, _itemH));
e.Graphics.FillRectangle(brush, new Rectangle(, , _itemW, this.Height));
if (Items != null)
{
Point p = this.PointToClient(Control.MousePosition);
StringFormat sf = new StringFormat()
{
LineAlignment = StringAlignment.Center
};
int index = ;
foreach (var v in Items)
{
Rectangle rect = new Rectangle(_itemW * index, , _itemW, _itemH);
Brush b = index == _titleIndex ? Brushes.BlueViolet : rect.Contains(p) ? Brushes.Gold : Brushes.Black;
if (index == ) rect.Offset(, );
e.Graphics.DrawString(v.Key, this.Font, b, rect, sf);
if (index == _titleIndex)
{
int i = ;
foreach (var item in v.Value)
{
rect = new Rectangle(, i * (_itemH - ) + _itemH, _itemW, (_itemH - ));
b = i == _itemIndex ? Brushes.White : rect.Contains(p) ? Brushes.LightGray : brush;
e.Graphics.FillRectangle(b, rect);
rect.Offset(, );
e.Graphics.DrawString(item.Name, this.Font, Brushes.Black, rect, sf);
i++;
}
}
index++;
}
}
e.Graphics.DrawLine(Pens.Gray, new Point(, _itemH), new Point(this.Width, _itemH));
brush.Dispose();
} /// <summary>
/// 初始化
/// </summary>
private void Initialize()
{
this.SetStyle(ControlStyles.AllPaintingInWmPaint | ControlStyles.OptimizedDoubleBuffer, true);
} private const int _itemH = ;
private const int _itemW = ;
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(, );
this.setterPanel.Name = "setterPanel";
this.setterPanel.Size = new System.Drawing.Size(, );
this.setterPanel.TabIndex = ;
//
// 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,否则会报错

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

【C#】自定义容器控件,设置界面控件,支持设计器拖入控件的更多相关文章

  1. Qt编写控件属性设计器11-导入xml

    一.前言 上一篇文章负责把设计好的控件数据导出到了xml文件,本偏文章负责把导出的xml数据文件导入,然后在画布上自动生成对应的控件,Qt内置的xml数据解析功能,非常强大,都封装在QtXml组件中, ...

  2. Qt编写控件属性设计器3-拉伸控件

    一.前言 插件控件加载了,拖曳控件也实现了,接下来就是一个最难点了,跟QtDesigner或者其他开发环境一样,能够任意自由的拉伸控件大小,移动位置,为了这个功能,还特别编写了一个控件来实现这个功能, ...

  3. Qt编写控件属性设计器2-拖曳控件

    一.前言 上一篇文章把插件加载好了,并且把插件中的所有控件都显示到了列表框中,这次要做的就是实现拖曳控件的功能,用户选择一个控件拖曳到画布上,松开,在松开位置处自动实例化该控件,这个需要用到dropE ...

  4. Qt编写控件属性设计器

    一.前言 自从研究Qt编写自定义控件以来,一发不可收拾,越多越多人有类似的需求找我定制控件,陆陆续续写了上百个控件,目前已超过150个,于是逐渐衍生了另外一个需求,提供一个控件属性设计器,类似QtDe ...

  5. Qt编写的项目作品2-控件属性设计器(组态)

    一.功能特点 自动加载插件文件中的所有控件生成列表,默认自带的控件超过120个. 拖曳到画布自动生成对应的控件,所见即所得. 右侧中文属性栏,改变对应的属性立即应用到对应选中控件,直观简洁,非常适合小 ...

  6. Qt编写控件属性设计器4-加载属性

    一.前言 控件能加载拖曳拉伸了,这些都是基本的前提工作,接下来的重点就是要动态加载选中控件的属性了,Qt的属性机制那是异常的强大,只能用强大到爆来形容,Qt中编写自定义控件,如果属性都用Q_PROPE ...

  7. WinForm编程时窗体设计器中ComboBox控件大小的设置

    问题描述: 在VS中的窗体设计器中拖放一个ComboBox控件后想调整控件的大小.发现在控件上用鼠标只能拖动宽度(Width)无法拖动(Height). 解决过程: 1.控件无法拖动,就在属性窗口中设 ...

  8. Qt编写控件属性设计器12-用户属性

    一.前言 用户属性是后面新增加的一个功能,自定义控件如果采用的Q_PROPERTY修饰的属性,会自动识别到属性栏中,这个一般称为控件属性,在组态设计软件中,光有控件本身的控件属性还是不够的,毕竟这些属 ...

  9. Qt编写控件属性设计器10-导出xml

    一.前言 能够导出控件布局和属性设置数据到xml文件或者其他文件,也是一个非常实用的功能,类似于QtDesigner中把页面设计好以后生成的.ui结尾的文件,其实就是xml文件,按照约定的规则存储好控 ...

随机推荐

  1. angular学习笔记(三十)-指令(10)-require和controller

    本篇介绍指令的最后两个属性,require和controller 当一个指令需要和父元素指令进行通信的时候,它们就会用到这两个属性,什么意思还是要看栗子: html: <outer‐direct ...

  2. linux命令返回值的妙用

    什么是返回值 在shell终端中,你所输入的一切命令其实都有返回值,而这个返回值默认保存在"$?"中,举例看一下 [root@localhost ~]# touch [root@l ...

  3. javascript基础拾遗(十一)

    1.DOM操作 1)查找 //根据id查找 document.getElementById() //根据html标签查找 documnet.getElementByTagName() //根据样式cl ...

  4. 【Acm】算法之美—Crashing Balloon

    题目概述:Crashing Balloon On every  June 1st, the Children's Day, there will be a game named "crash ...

  5. DLL中获取主程序句柄

    一.问题由来及说明 在实际编程中遇到一些系统模块(或API)调用初始化需要窗口句柄,在主程序中(MFC或者win32)都可以很容易获得,比如mfc中可以直接调用AfxGetMainWnd().GetS ...

  6. DIV+CSS网页设计规范

    1.网页HTML代码最前面必须包括W3C声明,以便符合标准: 一般网页: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transition ...

  7. 【Ubuntu】任务管理器loadruner

    linux1 准备工作   可以通过两种方法验证服务器上是否配置了rstatd守护程序:    ①使用rup命令,它用于报告计算机的各种统计信息,其中就包括rstatd的配置信息.使用命令rup 10 ...

  8. java中volatile关键字的理解

    一.基本概念 Java 内存模型中的可见性.原子性和有序性.可见性: 可见性是一种复杂的属性,因为可见性中的错误总是会违背我们的直觉.通常,我们无法确保执行读操作的线程能适时地看到其他线程写入的值,有 ...

  9. [转]Java中BigDecimal的使用

    原文地址:https://blog.csdn.net/cen_s/article/details/76472834 在日常开发中我们经常会碰到小数计算,而小数直接计算的话会出现一些小小的错误,如下 S ...

  10. highcharts图表组件通过设置tooltip属性自定义数据提示信息

    我们先来看看这样一个例子,全局配置好tooltip,数据点的提示信息能够自己根据数据点自身数据情况加以显示,代码如下所示: 01.$(function () { 02.$('#container'). ...