基于.NET的Windows窗体编程之WinForms自定义控件(2)

发布时间:2026/10/11 8:47:52

基于.NET的Windows窗体编程之WinForms自定义控件(2) 在实际应用开发中可能UI框架的默认控件已经不能满足实际的应用需求或者某些功能被大量的重复应用如果每一个使用的地方都书写大量的重复代码则不仅会浪费精力且让维护变得复杂此时就需要将包含特定功能的部分封装成控件便于重复使用。自定义控件就像造轮子轮子造好以后别的地方可以一键复用。今天我们以一些简单的小例子简述基于.NET的Windows窗体编程中自定义控件的相关应用仅供学习分享使用如有不足之处还请指正。概述一般而言自定义控件是在Visual Studio提供的默认控件不能满足实际的工作需要才需要在现有控件的基础之上进行新的扩展来实现自己的功能。自定义控件有自己特有的属性事件方法来支撑特定的功能。自定义控件封装实现的细节可以进行方便的复用。自定义控件主要有以下三种分类本例采用的是第三种。用户控件User Control又称之为复合控件Composite Controls将现有的各种控件组合起来形成一个新的控件来满足用户的需求。复合控件的设计方式与窗体类似具有可视化设计器。 通过视觉设计器创建、排列和修改构成控件。 控件事件和逻辑的编写方式与设计窗体时完全相同。 用户控件与其他任何控件一样放置在表单上。扩展控件Extended Controls就是在现有的控件基础上派生出一个新的控件增加新的功能或者修改原有功能来满足用户需求。自定义控件Custom Controls就是直接从UserControl类派生也就是说完全由自己来设计、实现一个全新的控件这是最灵活、最强大的方法。今天主要讲解扩展控件关于用户控件可以参考前一篇文章至于自定义控件将在后续篇幅继续讲解。扩展控件如果新的控件需要继承基本控件的功能则可以采用扩展控件新控件包含基本控件的所有功能和视觉方面但它为你提供了扩展它的机会。 今天我们以创建ToggleSwitch和ToggleLight为例简述扩展控件的应用方法。创建自定义控件库由于自定义控件可以在创建它的项目中使用也可也可以在引用这些用户控件库的其他项目中使用所以为了将自定义控件单独存放我们创建一个独立的自定义控件库“Okcoder.Winform.CustomControls”。1. 准备资源首先准备四张图片分别表示ToggleSwitch的开和关两种状态图片和ToggleLight的亮和灭两种状态图片如下所示在自定义控件库项目上点击右键在弹出的快捷菜单选择“属性”在打开的属性页面中选择“资源”Tab页然后在右侧点击“创建或打开程序集资源”如下图所示点击“创建或打开程序集资源”会在项目的Properties目录中创建Resources.resx文件如下所示打开Resources.resx文件然后将图片添加为资源这样图片就可以作为自定义控件库的资源如下所示2. 创建扩展控件选择控件库然后点击右键在弹出的快捷菜单中选择“添加”然后选择“新建项(W)...”在弹出的“添加新项”对话框中选择“自定义控件(Windows窗体)”然后输入名称点击“添加”按钮即可如下图所示在本实例中创建两个自定义控件分别命名为“ToggleSwitch”和“ToggleLight”分别表示开关控件和灯泡如下所示打开创建的扩展控件的代码视图然后修改控件的继承类默认为Control修改为需要扩展的控件类如ButtonCheckBox等。ToggleSwitch开关控件派生自CheckBox具备CheckBox的所有功能如下所示3. 重绘控件重写OnPaint方法在OnPaint方法中通过PaintEventArgs属性获取Graphics属性用于绘制图像。根据IsChecked属性分别绘制图片。当IsChecked属性为true时绘制open图片表示开关打开当IsChecked属性为false时绘制close图片表示开关关闭如下所示namespace Okcoder.Winform.CustomControls { public partial class ToggleSwitch: CheckBox { public ToggleSwitch() { InitializeComponent(); this.Appearance Appearance.Button; this.FlatStyle FlatStyle.Flat; } protected override void OnPaint(PaintEventArgs e) { var g e.Graphics; g.SmoothingMode SmoothingMode.AntiAlias; g.Clear(this.Parent.BackColor); if (this.Checked) { Image image Image.FromStream(new MemoryStream(Properties.Resources.open)); g.DrawImage(image, 0, 0, this.Width, this.Height); } else { Image image Image.FromStream(new MemoryStream(Properties.Resources.close)); g.DrawImage(image, 0, 0, this.Width, this.Height); } } } }在上述示例中图片从程序集资源中获取它是byte[]数组类型需要转换为MemoryStream然后再转换为Image图像进行绘制。ToggleLight控件的方法和ToggleSwitch一样只是显示的图片不同如下所示namespace Okcoder.Winform.CustomControls { public partial class ToggleLight: CheckBox { public ToggleLight() { InitializeComponent(); this.Appearance Appearance.Normal; this.FlatStyle FlatStyle.Flat; this.Enabled true; } protected override void OnPaint(PaintEventArgs e) { var g e.Graphics; g.SmoothingMode SmoothingMode.AntiAlias; g.Clear(this.Parent.BackColor); if (this.Checked) { Image image Image.FromStream(new MemoryStream(Properties.Resources.open1)); g.DrawImage(image, 0, 0, this.Width, this.Height); } else { Image image Image.FromStream(new MemoryStream(Properties.Resources.close1)); g.DrawImage(image, 0, 0, this.Width, this.Height); } } } }应用扩展控件扩展控件创建完成且项目编译成功后在需要应用用户控件的项目引用控件库“Okcoder.WinForm.CustomControls”就可以在工具箱中看到创建的自定义控件然后拖动控件到Form表单中如下所示为ToggleSwitch控件添加Click事件如下所示当鼠标点击ToggleSwitch控件时将ToggleSwitch控件的Checked属性赋值给ToggleLight的Checked属性属性所示namespace Okcoder.WinForm.Demo { public partial class FrmCustomControl : Form { public FrmCustomControl() { InitializeComponent(); } private void toggleSwitch1_Click(object sender, EventArgs e) { this.toggleLight1.Checked this.toggleSwitch1.Checked; } } }运行示例运行示例当点击开关控件时灯泡也会同时改变效果效果如下所示以上就是《基于.NET的Windows窗体编程之WinForms自定义控件(2)》的全部内容旨在抛砖引玉一起学习共同进步
延伸阅读

更多相关文章

2026/10/11 8:47:52

三轴V90 PN与SMART200伺服控制:从PROFINET通信到调试实战

最近又接手一个三轴V90和一台SMART200的老项目,调试完顺手把这几年的经验重新捋了一遍。三轴V90 PN与SMART200,说白了就是三台西门子V90伺服驱动器通过PROFINET总线挂在一台S7-200 SMART的PLC下面,组成一套三轴运动控制系统。它的核心价值不在…

2026/10/11 8:42:51

YOLOv8游戏自动化实战:目标检测、OCR识别与稳定性保障

简介:基于YOLOv8计算机视觉框架的游戏自动化测试与质量评估系统,面向游戏测试工程师、自动化测试开发与计算机视觉研究者,聚焦游戏画面识别、实时目标检测、自动化测试脚本、性能分析、异常监控、元素定位、动态场景处理与多分辨率适配。包内…

2026/10/11 13:13:09

Jmeter接口测试实战:从HTTP基础到参数化、断言与压测

1. 项目概述:接口测试为什么要选Jmeter先开门见山说结论:用Jmeter做HTTP接口测试,是目前中小团队和个人测试最“性价比”的选择之一。你不需要写一段复杂的Java代码,不需要维护一套平台,只要把Jmeter装好,按…

2026/10/11 13:13:09

K8s离线部署flannel镜像包全攻略:从拉取到导入避坑

简介:这份资源面向正在搭建 Kubernetes 集群、需要为节点配置网络插件的运维与开发人员,解决 k8s 安装过程中 flannel 网络组件镜像难以获取、离线环境拉取不便的问题。压缩包共 3 个文件,以 2 个 tar 镜像包和 1 个 yaml 清单为主&#xff0…

2026/10/11 13:13:09

CSAPP实验1全攻略:工具链、链接加载与进程漫游避坑详解

简介:面向哈工大计算机专业学生的《计算机系统漫游》实验1配套资料包,聚焦课程入门实践,帮助初学者打通从二进制到系统调用的完整知识链。压缩包大小约969MB,内含实验指导文档、可运行代码样例及配套数据文件,目录按知…

2026/10/11 13:08:09

jocky代码混淆工具:Eclipse集成与Maven配置实战指南

简介:Jocky是一款面向Java开发者的代码混淆工具,以Eclipse插件形式提供,适合需要在日常开发流程中直接完成源码级混淆的工程师使用。与常见混淆编译器不同,Jocky直接从源码入手,编译过程本身即完成混淆,无需…

2026/10/11 0:02:13

Python调用Gemini Structured Outputs实现工单路由门禁

客服工单最怕的不是模型“答错一句话”,而是它给出一段看起来合理的说明,程序却从中猜错优先级。通俗做法是:要求模型只交 JSON(JavaScript Object Notation,轻量数据格式),再让代码验证它。Gem…

2026/10/11 0:02:13

Spring Boot超市进销存系统毕设实战:从需求拆解到答辩通关

最近带的一个学生项目组里,有A同学跑来问我:选什么毕设题目最稳妥,既能让评审老师觉得工作量够,又不会在答辩时被问到语无伦次。我第一反应就是推荐基于Spring Boot的超市仓库管理系统——也就是超市进销存系统。这个题目乍一看平…

2026/10/11 0:02:13

Flutter StatefulWidget 生命周期核心解析

很多刚开始接触 Flutter 的朋友,在看完一堆“Hello World”和基础组件之后,大概率都会撞上同一堵墙:StatefulWidget 里那堆 initState、build、dispose 方法,到底什么时候被调用?为什么顺序是那样?在里面到…

2026/10/11 0:02:13

Python调用Gemini Structured Outputs实现工单路由门禁

客服工单最怕的不是模型“答错一句话”,而是它给出一段看起来合理的说明,程序却从中猜错优先级。通俗做法是:要求模型只交 JSON(JavaScript Object Notation,轻量数据格式),再让代码验证它。Gem…

2026/10/11 0:02:13

Spring Boot超市进销存系统毕设实战:从需求拆解到答辩通关

最近带的一个学生项目组里,有A同学跑来问我:选什么毕设题目最稳妥,既能让评审老师觉得工作量够,又不会在答辩时被问到语无伦次。我第一反应就是推荐基于Spring Boot的超市仓库管理系统——也就是超市进销存系统。这个题目乍一看平…

2026/10/11 0:02:13

Flutter StatefulWidget 生命周期核心解析

很多刚开始接触 Flutter 的朋友,在看完一堆“Hello World”和基础组件之后,大概率都会撞上同一堵墙:StatefulWidget 里那堆 initState、build、dispose 方法,到底什么时候被调用?为什么顺序是那样?在里面到…

还想了解更多?直接咨询顾问

免费诊断 + 免费方案 + 透明报价。

全国咨询热线400-8866-253
免费获取方案
☎咨询二维码 ☎ ↑