WinForm自定义控件

📅 2026/7/8 2:32:27
WinForm自定义控件
WinForm 自定义控件完整知识点汇总一、自定义控件三大分类1. 复合控件UserControl 用户控件定义拖拽现有基础控件Button/Label/TextBox组合封装.cs .Designer.cs配套设计器界面。适用场景重复复用的业务模块登录框、商品卡片、分页栏。优点可视化拖拽开发、上手简单、自带设计器预览。缺点无法修改基础控件原生绘制样式只能组合。csharp运行// 创建方式右键项目 → 添加 → 用户控件(Windows窗体) public partial class UserControl1 : UserControl { public UserControl1() { InitializeComponent(); } }2. 扩展控件继承原生控件定义继承系统自带控件Button/Label/TextBox重写方法扩展功能。适用场景改造原生控件新增样式、事件、属性圆角按钮、水印输入框。优点复用原生控件全部逻辑仅新增自定义逻辑体积轻量。示例自定义圆角按钮csharp运行public class RoundButton : Button { protected override void OnPaint(PaintEventArgs pevent) { // 重绘实现圆角 base.OnPaint(pevent); } }3. 完全绘制控件继承 Control 基类定义直接继承Control无内置子控件所有文字、图形全部手动GDI绘制。适用场景全新视觉组件进度条、仪表盘、色块开关。优点高度自定义外观无多余原生逻辑性能可控。缺点需要手动处理鼠标、绘制、布局所有逻辑代码量大。csharp运行public class MyProgress : Control { protected override void OnPaint(PaintEventArgs e) { // GDI 手动绘制矩形、文字 Graphics g e.Graphics; g.FillRectangle(Brushes.Blue,0,0,this.Width,this.Height); } }二、核心基础知识点1. 自定义公开属性供设计器 / 代码赋值基础属性写法csharp运行private int _radius 10; // 加[Category] [Description] 在属性面板分组、显示注释 [Category(自定义样式)] [Description(控件圆角大小)] public int Radius { get _radius; set { _radius value; this.Invalidate(); // 修改后重绘控件刷新界面 } }关键this.Invalidate()触发OnPaint重新绘制属性修改立刻生效。2. 自定义事件外部窗体订阅回调定义事件委托触发事件的保护虚方法OnXXX满足条件时调用事件csharp运行// 1. 声明事件 public event EventHandler ValueChanged; // 2. 保护虚方法规范触发入口 protected virtual void OnValueChanged() { ValueChanged?.Invoke(this, EventArgs.Empty); } // 业务逻辑中触发 private void UpdateValue() { OnValueChanged(); }3. GDI 绘制核心重写方法所有绘制逻辑写在OnPaint禁止在其他地方创建Graphicscsharp运行// 控件首次加载、大小改变、调用Invalidate时自动执行 protected override void OnPaint(PaintEventArgs e) { base.OnPaint(e); // 执行父类原有绘制逻辑复合控件/扩展控件必写 Graphics g e.Graphics; g.SmoothingMode System.Drawing.Drawing2D.SmoothingMode.AntiAlias; // 抗锯齿消除锯齿 // 绘制矩形、圆形、文字、图片 }配套刷新方法Invalidate()全局重绘整个控件Invalidate(Rectangle)局部区域重绘优化性能Refresh()Invalidate() 立刻同步绘制4. 鼠标交互重写方法捕获鼠标移入、点击、拖动状态修改绘制样式csharp运行protected override void OnMouseEnter(EventArgs e) // 鼠标进入 { base.OnMouseEnter(e); isHover true; this.Invalidate(); } protected override void OnMouseLeave(EventArgs e) // 鼠标离开 { base.OnMouseLeave(e); isHover false; this.Invalidate(); } protected override void OnMouseDown(MouseEventArgs e) // 鼠标按下 { base.OnMouseDown(e); isPress true; this.Invalidate(); } protected override void OnMouseUp(MouseEventArgs e) // 鼠标抬起 { base.OnMouseUp(e); isPress false; this.Invalidate(); }5. 大小自适应重写控件尺寸改变时自动重绘csharp运行protected override void OnSizeChanged(EventArgs e) { base.OnSizeChanged(e); this.Invalidate(); // 尺寸变化重新绘制图形 }三、设计器相关特性可视化支持[Category(分组名)]属性面板分组归类[Description(文字说明)]选中属性底部显示注释[DefaultValue(默认值)]标记属性默认值设计器灰色区分[Browsable(false)]隐藏属性不在属性面板显示[ReadOnly(true)]属性只读设计器无法修改csharp运行[Category(自定义)] [Description(背景颜色)] [DefaultValue(typeof(Color),LightBlue)] public Color BgColor { get; set; }四、UserControl 复合控件关键要点内部子控件访问限制内部控件默认private需要对外暴露则封装属性布局适配使用Dock/Anchor实现子控件随控件拉伸自适应消息转发内部按钮点击事件封装为自定义事件外部窗体直接订阅加载顺序UserControl构造函数→Load事件→OnPaint绘制。五、性能优化规范绘制时开启SmoothingMode.AntiAlias抗锯齿频繁刷新使用局部Invalidate(rect)避免全局重绘Graphics、Pen、Brush实现IDisposable使用using自动释放资源防止 GDI 泄漏csharp运行using (Pen pen new Pen(Color.Red,2)) { e.Graphics.DrawRectangle(pen,0,0,50,50); }避免在OnPaint中 new 大量绘图对象可缓存画笔 / 画刷为全局私有字段。六、部署与复用同项目内直接在工具箱自动加载自定义控件拖拽到窗体跨项目复用将自定义控件单独封装为类库ClassLibrary生成.dll其他项目工具箱右键选择项导入 dll工具箱不显示解决方案生成项目重新编译控件类必须public无带参数构造函数必须保留无参构造七、高频易错点总结忘记base.OnPaint(e)父类原有绘制丢失原生控件文字、背景消失修改属性不调用Invalidate()界面不会刷新修改无视觉效果绘图资源不释放长期运行 GDI 句柄泄漏软件卡顿崩溃自定义控件缺少无参构造函数工具箱无法加载控件直接在子线程修改控件属性 / 调用 Invalidate触发跨线程报错必须Invoke切 UI 线程复合控件内部子控件直接 public 暴露破坏封装推荐封装属性中转。八、三类控件选型速查表表格控件类型继承基类开发难度适用场景UserControl 复合控件UserControl低多基础控件组合业务模块扩展改造控件Button/Label/TextBox中原生控件新增样式、功能完全自绘控件Control高全新自定义视觉组件