c# 如何自定义一个 control

技术百科 畫卷琴夢 发布时间:2026-01-27 浏览:
继承 Control 类是 WinForms 自定义控件最直接方式,需禁用默认背景擦除、启用双缓冲与焦点支持,并提供无参构造函数及设计器特性以确保可用性。

继承 Control 类是最直接的方式

自定义控件本质是扩展 System.Windows.Forms.Control(WinForms)或 System.Windows.Controls.Control(WPF),前者更轻量、适合底层绘制与事件控制。不建议从 UserControl 开始——它自带容器逻辑和设计器依赖,反而限制对绘制、消息循环、焦点行为的精细控制。

  • 若需完全掌控绘制(比如画波形图、仪表盘),继承 Control 并重写 OnPaint
  • 若要支持双缓冲防闪烁,设 this.SetStyle(ControlStyles.OptimizedDoubleBuffer | ControlStyles.AllPaintingInWmPaint, true)
  • 必须手动调用 base.OnCreateControl()base.OnHandleCreated(),否则生命周期钩子可能失效
  • 别忘了在构造函数里设 ResizeRedraw = true,否则窗口缩放时不会自动重绘

重写 OnPaint 时绕开 GDI+ 默认背景擦除

默认 Control 在每次 OnPaint 前会用 BackColor 填充整个客户区,这会导致自绘内容被覆盖或出现残影。尤其在动画或高频刷新场景下特别明显。

  • 在构造函数中关闭默认擦除:this.SetStyle(ControlStyles.Opaque, true)

  • 同时禁用背景绘制:this.SetStyle(ControlStyles.ResizeRedraw, true)
  • 重写 OnPaintBackground 为空实现,避免父类填充背景
  • OnPaint 中只用传入的 Graphics 绘制内容,不要调用 e.Graphics.Clear(...)
protected override void OnPaint(PaintEventArgs e) {
    // 不调用 base.OnPaint(e)
    using (var pen = new Pen(Color.Blue, 2)) {
        e.Graphics.DrawLine(pen, 10, 10, 100, 100);
    }
}

响应鼠标/键盘事件必须显式启用焦点支持

直接继承 Control 的控件默认不可聚焦,KeyDownKeyPress 等事件根本不会触发,哪怕你重写了 OnKeyDown

  • 构造函数中调用 this.TabStop = truethis.TabIndex = 0
  • 重写 CanSelect 属性返回 true
  • OnMouseDown 中主动调用 this.Focus(),否则点击不会获得输入焦点
  • 若需捕获非客户端区域(如边框)的鼠标,需处理 WM_NCHITTEST 消息,通过 WndProc 拦截

设计器支持需要 [ToolboxItem] 和默认构造函数

没有无参构造函数或缺少特性标记,控件拖不到 WinForms 设计器里,且属性面板不显示自定义属性。

  • 必须提供 public 无参构造函数:public MyCustomControl() { InitializeComponent(); }
  • 添加 [ToolboxItem(true)] 特性,否则设计器忽略该类型
  • 让属性可序列化:对希望在设计器中编辑的属性加 [Browsable(true)][DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
  • 若属性影响外观(如 LineColor),重写 OnPropertyChanged 并调用 Invalidate() 触发重绘
WinForms 自定义控件最难缠的不是绘制,而是消息分发边界——比如鼠标进入区域后移出但未触发 MouseLeave,或键盘焦点在嵌套控件间跳转时丢失。这些往往要靠精确拦截 WndProc 和检查 NativeWindow.AssignHandle 状态来定位。


# ai  # 会用  # 写了  # windows  # 重写  # 自带  # 若需  # 自定义  # 跳转  # 可用性  # 鼠标  # public  # win  # 循环  # c#  # 构造函数  # 键盘事件  # 事件  # red  # this  # 继承  # wpf  # 父类  # 重绘  # 擦除 


相关栏目: <?muma $count = M('archives')->where(['typeid'=>$field['id']])->count(); ?> 【 AI推广<?muma echo $count; ?> 】 <?muma $count = M('archives')->where(['typeid'=>$field['id']])->count(); ?> 【 SEO优化<?muma echo $count; ?> 】 <?muma $count = M('archives')->where(['typeid'=>$field['id']])->count(); ?> 【 技术百科<?muma echo $count; ?> 】 <?muma $count = M('archives')->where(['typeid'=>$field['id']])->count(); ?> 【 谷歌推广<?muma echo $count; ?> 】 <?muma $count = M('archives')->where(['typeid'=>$field['id']])->count(); ?> 【 百度推广<?muma echo $count; ?> 】 <?muma $count = M('archives')->where(['typeid'=>$field['id']])->count(); ?> 【 网络营销<?muma echo $count; ?> 】 <?muma $count = M('archives')->where(['typeid'=>$field['id']])->count(); ?> 【 案例网站<?muma echo $count; ?> 】 <?muma $count = M('archives')->where(['typeid'=>$field['id']])->count(); ?> 【 精选文章<?muma echo $count; ?>

相关推荐

在线咨询

点击这里给我发消息QQ客服

在线咨询

免费通话

24h咨询:4006964355


如您有问题,可以咨询我们的24H咨询电话!

免费通话

微信扫一扫

微信联系
返回顶部