【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 = ;
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#】自定义容器控件,设置界面控件,支持设计器拖入控件的更多相关文章
- Qt编写控件属性设计器11-导入xml
一.前言 上一篇文章负责把设计好的控件数据导出到了xml文件,本偏文章负责把导出的xml数据文件导入,然后在画布上自动生成对应的控件,Qt内置的xml数据解析功能,非常强大,都封装在QtXml组件中, ...
- Qt编写控件属性设计器3-拉伸控件
一.前言 插件控件加载了,拖曳控件也实现了,接下来就是一个最难点了,跟QtDesigner或者其他开发环境一样,能够任意自由的拉伸控件大小,移动位置,为了这个功能,还特别编写了一个控件来实现这个功能, ...
- Qt编写控件属性设计器2-拖曳控件
一.前言 上一篇文章把插件加载好了,并且把插件中的所有控件都显示到了列表框中,这次要做的就是实现拖曳控件的功能,用户选择一个控件拖曳到画布上,松开,在松开位置处自动实例化该控件,这个需要用到dropE ...
- Qt编写控件属性设计器
一.前言 自从研究Qt编写自定义控件以来,一发不可收拾,越多越多人有类似的需求找我定制控件,陆陆续续写了上百个控件,目前已超过150个,于是逐渐衍生了另外一个需求,提供一个控件属性设计器,类似QtDe ...
- Qt编写的项目作品2-控件属性设计器(组态)
一.功能特点 自动加载插件文件中的所有控件生成列表,默认自带的控件超过120个. 拖曳到画布自动生成对应的控件,所见即所得. 右侧中文属性栏,改变对应的属性立即应用到对应选中控件,直观简洁,非常适合小 ...
- Qt编写控件属性设计器4-加载属性
一.前言 控件能加载拖曳拉伸了,这些都是基本的前提工作,接下来的重点就是要动态加载选中控件的属性了,Qt的属性机制那是异常的强大,只能用强大到爆来形容,Qt中编写自定义控件,如果属性都用Q_PROPE ...
- WinForm编程时窗体设计器中ComboBox控件大小的设置
问题描述: 在VS中的窗体设计器中拖放一个ComboBox控件后想调整控件的大小.发现在控件上用鼠标只能拖动宽度(Width)无法拖动(Height). 解决过程: 1.控件无法拖动,就在属性窗口中设 ...
- Qt编写控件属性设计器12-用户属性
一.前言 用户属性是后面新增加的一个功能,自定义控件如果采用的Q_PROPERTY修饰的属性,会自动识别到属性栏中,这个一般称为控件属性,在组态设计软件中,光有控件本身的控件属性还是不够的,毕竟这些属 ...
- Qt编写控件属性设计器10-导出xml
一.前言 能够导出控件布局和属性设置数据到xml文件或者其他文件,也是一个非常实用的功能,类似于QtDesigner中把页面设计好以后生成的.ui结尾的文件,其实就是xml文件,按照约定的规则存储好控 ...
随机推荐
- 《java虚拟机》汇总所有关键要点
一 .java虚拟机底层结构详解 我们知道,一个JVM实例的行为不光是它自己的事,还涉及到它的子系统.存储区域.数据类型和指令这些部分,它们描述了JVM的一个抽象的内部体系结构,其目的不光规定实现J ...
- C++技术沙龙报名开始啦!
沙龙主题:C++甜点关键字:C++之美,黑科技,神奇和魔力内容:三场主题演讲和一场开放性话题讨论时间:2015年5月16日下午2:00-6:00地点:珠海金山办公软件1楼VIP厅,珠海市吉大景山路莲山 ...
- python(49):把文件压缩成zip格式的文件
有时需要用到压缩文件,网上搜集了一段代码: 分享一下: import os import zipfile def make_zip(localPath, pname): zipf = zipfile. ...
- 读取本地已有的.db数据库
public class MyDB extends SQLiteOpenHelper { // 数据库的缺省路径 private static String DB_PATH ; private sta ...
- 【驱动】网卡驱动·linux内核网络分层结构
Preface Linux内核对网络驱动程序使用统一的接口,并且对于网络设备采用面向对象的思想设计. Linux内核采用分层结构处理网络数据包.分层结构与网络协议的结构匹配,既能简化数据包处理流程 ...
- 7款让人惊叹的HTML5粒子动画特效
HTML5的很大一个优势就是可以更加便捷高效地制作网页粒子动画特效,特别是Canvas特性,可以实现在网页上绘制任何图形和动画.本文要分享7款让人惊叹的HTML5粒子动画特效,这些粒子特效都提供源代码 ...
- Pandas Dataframe增、删、改、查、去重、抽样基本操作
总括 pandas的索引函数主要有三种: loc 标签索引,行和列的名称 iloc 整型索引(绝对位置索引),绝对意义上的几行几列,起始索引为0 ix 是 iloc 和 loc的合体 at是loc的快 ...
- iOS贝塞尔曲线(UIBezierPath)的基本使用方法
简介 UIBezierPath是对Core Graphics框架的一个封装,使用UIBezierPath类我们可以画出圆形(弧线)或者多边形(比如:矩形)等形状,所以在画复杂图形的时候会经常用到. 分 ...
- 将本地的项目推送到github上
好像还是不能用git在本地直接建一个repository,然后推送到github,这是把本地项目推送到github上已经建好的裤 …or create a new repository on the ...
- Quartz TriggerListener 触发器监听器
Quartz Scheduler 可以对Trigger建立一个监听器,分别对Trigger的各种状态进行监听 实现监听器需要实现TriggerListener接口,然后注册到Scheduler上就可 ...