当前位置: 首页 > article >正文

【C#】WinForm自定义控件及窗体

前言

WinForm(Windows Forms)是Microsoft.NET框架中的技术,用于开发Windows桌面应用程序。它提供了一套丰富的控件和组件。通过拖放控件、编写事件处理程序等方式快速构建用户界面。

通过属性窗口定制这些控件的外观和行为。
通过数据绑定,将UI控件与数据源连接,实现数据的展示和更新。
通过上面的方法可以帮助开发者高效地创建桌面窗体应用程序,尤其适合初学者和需要快速开发的项目。

本文介绍了如何创建Winform窗体,并自定义窗体样式和窗体的基本功能。

1、窗体关闭、最大化、最小化、适应。
2、无边框窗体移动、调整窗体大小。
3、菜单展开折叠。

界面预览

在这里插入图片描述

代码

自定义按钮

用户自定义按钮:        

SelectedState:用户点击后状态取反。
Radius:按钮圆角半径。
HoverColor:鼠标悬停时的背景色。

public class UCButton : Button
{#region  公共字段、属性private bool _selectedState = false;[Category("UserProperty")][Description("选中状态")]public bool SelectedState{get => _selectedState;private set{_selectedState = value;this.Invalidate();}}private int radius = 15;[Category("UserProperty")][Description("圆角半径")]public int Radius{get { return radius; }set{radius = value;this.Invalidate();}}private Color _defaultColor;private Color _hoverColor = Color.LightBlue;[Category("UserProperty")][Description("鼠标悬停时的背景色")]public Color HoverColor { get => _hoverColor; set => _hoverColor = value; }#endregionpublic UCButton(){Initialize();}private void Initialize(){this.DoubleBuffered = true;this.FlatStyle = FlatStyle.Flat;this.FlatAppearance.BorderSize = 0;this.SetStyle(ControlStyles.UserPaint| ControlStyles.AllPaintingInWmPaint| ControlStyles.OptimizedDoubleBuffer| ControlStyles.ResizeRedraw| ControlStyles.SupportsTransparentBackColor, true);_defaultColor = BackColor;this.MouseEnter += UCButton_MouseEnter;this.MouseLeave += UCButton_MouseLeave;}private void UCButton_MouseEnter(object sender, EventArgs e){this.BackColor = HoverColor; // 鼠标进入时更改背景色}private void UCButton_MouseLeave(object sender, EventArgs e){this.BackColor = _defaultColor; // 鼠标离开时恢复默认背景色}protected override void OnClick(EventArgs e){base.OnClick(e);_selectedState = !_selectedState;}protected override void OnPaint(PaintEventArgs e){base.OnPaint(e);e.Graphics.SmoothingMode = SmoothingMode.AntiAlias;                     // 设置抗锯齿e.Graphics.CompositingQuality = CompositingQuality.HighQuality;         // 高质量合成e.Graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;    // 高质量插值// 绘制圆角矩形using (GraphicsPath path = new GraphicsPath()){path.AddArc(0, 0, radius, radius, 180, 90);                         // 左上角path.AddArc(this.Width - radius, 0, radius, radius, 270, 90);       // 右上角path.AddArc(this.Width - radius, this.Height - radius, radius, radius, 0, 90);  // 右下角path.AddArc(0, this.Height - radius, radius, radius, 90, 90);                   // 左下角path.CloseFigure();this.Region = new Region(path); // 设置按钮的区域为圆角矩形}// 绘制按钮文本using (Brush brush = new SolidBrush(this.ForeColor)){SizeF textSize = e.Graphics.MeasureString(this.Text, this.Font);PointF textLocation = new PointF((this.Width - textSize.Width) / 2, (this.Height - textSize.Height) / 2);e.Graphics.DrawString(this.Text, this.Font, brush, textLocation);}}
}

窗体代码

1、窗体关闭、最大化、最小化、适应。
2、无边框窗体移动、调整窗体大小。
3、菜单展开折叠。

public partial class MainForm : Form
{private int ButtonWidth = 62;#region 窗体初始化、加载、关闭public MainForm(){InitializeComponent();this.CenterToParent();this.CenterToScreen();}private void MainForm_Load(object sender, System.EventArgs e){WinMoveBinding(panel_TopBorderItem);WinMoveBinding(pic_WinIcon);this.WindowState = FormWindowState.Normal;this.MinimumSize = new System.Drawing.Size(150, 150);panel_MenuItemText.Hide();ButtonWidth = btn_Expand.Width;}private void MainForm_FormClosing(object sender, FormClosingEventArgs e){}#endregion/// <summary>/// 窗体移动功能事件绑定/// </summary>private void WinMoveBinding(Control control){control.MouseDown += topBorderPanel_MouseDown;control.MouseMove += topBorderPanel_MouseMove;control.MouseUp += topBorderPanel_MouseUp;}#region 窗体拖动private Point mouseOffset;private void topBorderPanel_MouseDown(object sender, MouseEventArgs e){if (e.Button == MouseButtons.Left){mouseOffset = new Point(-e.X, -e.Y);}}private void topBorderPanel_MouseMove(object sender, MouseEventArgs e){if (e.Button == MouseButtons.Left){Point mousePos = Control.MousePosition;mousePos.Offset(mouseOffset.X, mouseOffset.Y);this.Location = mousePos;}}private void topBorderPanel_MouseUp(object sender, MouseEventArgs e){mouseOffset = Point.Empty;}#endregion#region 无边框窗体随意拖动和改变尺寸const int WM_NCHITTEST = 0x0084;const int HTLEFT = 10;const int HTRIGHT = 11;const int HTTOP = 12;const int HTTOPLEFT = 13;const int HTTOPRIGHT = 14;const int HTBOTTOM = 15;const int HTBOTTOMLEFT = 0x10;const int HTBOTTOMRIGHT = 17;protected override void WndProc(ref Message m){base.WndProc(ref m);switch (m.Msg){case WM_NCHITTEST:Point vPoint = new Point((int)m.LParam & 0xFFFF,(int)m.LParam >> 16 & 0xFFFF);vPoint = PointToClient(vPoint);if (vPoint.X <= 5)if (vPoint.Y <= 5)m.Result = (IntPtr)HTTOPLEFT;else if (vPoint.Y >= ClientSize.Height - 5)m.Result = (IntPtr)HTBOTTOMLEFT;else m.Result = (IntPtr)HTLEFT;else if (vPoint.X >= ClientSize.Width - 5)if (vPoint.Y <= 5)m.Result = (IntPtr)HTTOPRIGHT;else if (vPoint.Y >= ClientSize.Height - 5)m.Result = (IntPtr)HTBOTTOMRIGHT;else m.Result = (IntPtr)HTRIGHT;else if (vPoint.Y <= 5)m.Result = (IntPtr)HTTOP;else if (vPoint.Y >= ClientSize.Height - 5)m.Result = (IntPtr)HTBOTTOM;break;}}#endregion#region 窗体关闭、最大化、最小化private void btn_ClosingWindow_Click(object sender, System.EventArgs e){if (MessageBox.Show("是否关闭窗体!", "关闭", MessageBoxButtons.OKCancel, MessageBoxIcon.Warning) == DialogResult.OK){this.Close();}}private void btn_Maximize_Click(object sender, System.EventArgs e){Button button = sender as Button;if (this.WindowState == FormWindowState.Maximized){this.WindowState = FormWindowState.Normal;button.Image = global::ModbusDemo.Properties.Resources.maximize_blue_32;}else{this.WindowState = FormWindowState.Maximized;button.Image = global::ModbusDemo.Properties.Resources.restore_blue_32;}}private void btn_Minimize_Click(object sender, System.EventArgs e){this.WindowState = FormWindowState.Minimized;}#endregion/// <summary>/// 折叠按钮/// </summary>private void btn_Expand_Click(object sender, System.EventArgs e){//展开if (!btn_Expand.SelectedState){btn_Expand.Image = global::ModbusDemo.Properties.Resources.collapse_left_blue_32;panel_MenuItemIcon.Width = ButtonWidth;panel_MenuItemText.ScrollControlIntoView(btn_Expand);panel_MenuItemText.Show();panel_LeftMenuItem.Width = 256;}//折叠else{btn_Expand.Image = global::ModbusDemo.Properties.Resources.collapse_right_blue_32;panel_MenuItemIcon.Width = ButtonWidth;panel_LeftMenuItem.Width = ButtonWidth;panel_MenuItemText.Hide();}}/// <summary>/// 首页按钮/// </summary>private void btn_Home_Click(object sender, EventArgs e){}
}

结语

既是分享,也是备份。

相关文章:

【C#】WinForm自定义控件及窗体

前言 WinForm&#xff08;Windows Forms&#xff09;是Microsoft.NET框架中的技术&#xff0c;用于开发Windows桌面应用程序。它提供了一套丰富的控件和组件。通过拖放控件、编写事件处理程序等方式快速构建用户界面。 通过属性窗口定制这些控件的外观和行为。 通过数据绑定&am…...

基于虚拟知识图谱的语义化决策引擎

在数字化转型浪潮中&#xff0c;企业数据资产的价值释放面临两大挑战&#xff1a;海量异构数据的整合困局与业务-技术语义鸿沟。本文解析飞速创软灵燕智能体平台的创新解决方案——通过构建业务语义驱动的虚拟知识图谱系统&#xff0c;实现企业数据的智能认知与决策赋能。 一、…...

七天免登录 为什么不能用seesion,客户端的http请求自动携带cookei的机制(比较重要)涉及HTTP规范

如果是七天免登录,和session肯定没关系,因为session不能持久化,主要是客户端一旦关闭,seesion就失效了/// 所以必须是能持久化的&#xff0c;这就清晰了&#xff0c;要莫在的服务器保存&#xff0c;要摸在客户端设置 cook机制 1. 使用Cookie实现七天免登录 前端&#xff08;登…...

HarmonyOS:@AnimatableExtend 装饰器自学指南

在最近的项目开发中&#xff0c;我遇到了需要实现复杂动画效果的需求。在探索解决方案的过程中&#xff0c;我发现了 AnimatableExtend 装饰器&#xff0c;它为实现动画效果提供了一种非常灵活且强大的方式。然而&#xff0c;在学习这个装饰器的过程中&#xff0c;我发现相关的…...

主流NoSQL数据库类型及选型分析

在数据库领域&#xff0c;不同类型的数据库针对不同场景设计&#xff0c;以下是四类主流NoSQL数据库的对比分析&#xff1a; 一、核心特性对比 键值数据库&#xff08;Key-Value&#xff09; 数据模型&#xff1a;简单键值对存储 特点&#xff1a;毫秒级读写、高并发、无固定…...

kubernetes|云原生|kubeadm-1.25.7集群单master+外部etcd集群+kubeadm-init+cri-docker文件形式快速部署

一、 前言和写作原因 本文做一个kubernetes集群部署记录&#xff0c;实在是部署的东西太多了&#xff0c;害怕忘记&#xff0c;kubernetes集群的部署又细节比较多&#xff0c;因此&#xff0c;在这里做一个尽量详细的记录 三个VMware虚拟机&#xff0c;IP分别为192.168.123.…...

Qt 导入TagLib库

文章目录 0. 前言和环境介绍1. 下载TagLib2. 下载zlib3. 修改.pro文件4. 测试代码 0. 前言和环境介绍 最近在使用Qt写一个播放器&#xff0c;需要解析mp3文件&#xff0c;于是研究了一下如何导入TagLib库 Qt构建套件:Desktop Qt6.8.2 MinGW64-bit Qt Creator安装目录: D:\bit…...

新能源汽车充换站如何实现光储充一体化管理?

长三角某换电站光伏板晒到发烫&#xff0c;却因电网限电被迫切机&#xff1b;北京五环充电站每月多缴6万超容费&#xff1b;深圳物流车充电高峰排队3小时...当95%的充换站深陷“用不起绿电、扛不住扩容、算不清碳账”困局&#xff0c;安科瑞用一组真实数据撕开行业潜规则&#…...

【数据分享】2000—2024年我国省市县三级逐年归一化植被指数(NDVI)数据(年平均值/Shp/Excel格式)

之前我们分享过2000-2024年我国逐年的归一化植被指数&#xff08;NDVI&#xff09;栅格数据&#xff0c;该逐年数据是取的当年月归一化植被指数&#xff08;NDVI&#xff09;的年平均值。&#xff01;该数据来源于NASA定期发布的MOD13A3数据集&#xff01;很多小伙伴拿到数据后…...

【leetcode题解】链表

目录 链表 两数相加 两两交换链表中的节点 重排链表 合并 K 个升序链表&#xff08;困难&#xff09; K 个一组翻转链表 链表 1. 常用技巧 画图&#xff01;&#xff01;&#xff01;&#xff08;直观形象&#xff0c;便于我们理解&#xff09;引入虚拟“头”节点&#xf…...

本地部署Dify 添加Ollama模型DeepSeek

1、准备工作 本地ollama 加载DeepSeek。 安装并登录Dify。 2、添加Ollama模型服务商 在设置-》模型服务上里添加Ollama模型服务商&#xff0c;也叫插件。 3、添加DeepSeek 使用终端命令 ollama list查询deepseek名称&#xff0c;如deepseek-r1:14b。 在Ollama插件冲添加…...

QEMU源码全解析 —— 块设备虚拟化(7)

接前一篇文章:QEMU源码全解析 —— 块设备虚拟化(6) 本文内容参考: 《趣谈Linux操作系统》 —— 刘超,极客时间 《QEMU/KVM源码解析与应用》 —— 李强,机械工业出版社 特此致谢! QEMU初始化阶段的块设备虚拟化 从模板生成类和类的实例化 上一回在讲解QEMU中类继承…...

图论 | 岛屿数量(深搜,广搜)

岛屿数量 acm模式&#xff1a;99.岛屿数量 核心代码模式&#xff1a; 200. 岛屿数量 思路 遍历grid&#xff0c;如果它是1&#xff0c;则通过bfs/dfs将这个小岛的grid变为0 dfs def dfs(grid,i,j):if i<0 or j<0 or i>len(grid) or j>len(grid[0]):returnif g…...

iOS:GCD信号量、同步、异步的使用方法

信号量的详细用法&#xff0c;可以用此方法进行队列管理 -(void)dispatchSignal{//crate的value表示&#xff0c;最多几个资源可访问dispatch_semaphore_t semaphore dispatch_semaphore_create(3);dispatch_queue_t quene dispatch_get_global_queue(DISPATCH_QUEUE_PRIORI…...

MSP430 Proteus 仿真作品

https://www.dong-blog.fun/post/1998 1 、 电子万年历&#xff08;采用 DS1302 及 及 TC72 等芯片&#xff09; 基本要求&#xff1a; 可显示年、月、日、星期、时、分、秒&#xff1b; 有温度显示功能。 发挥部分&#xff1a; 可调节时间和日期&#xff1b; 有农历显示功能 &…...

Windows打开ftp局域网共享

前提是windows已经设置好开机账号密码了&#xff0c;否则教程不适用 第一先打开电脑ftp共享配置 点击保存即可 2.设置要共享到其他电脑的文件路径&#xff08;如果你要共享整个盘你就设置整个盘&#xff0c;如果是共享盘中某文件就设置某文件&#xff0c;这里是某文件&#x…...

基于HTML的邮件发送状态查询界面设计示例

以下是一个基于HTML的邮件发送状态查询界面设计示例&#xff0c;结合筛选功能、状态展示和重新发送操作&#xff0c;采用Bootstrap框架实现响应式布局&#xff1a; <!DOCTYPE html> <html lang"zh-CN"> <head><meta charset"UTF-8"&…...

聊聊langchain4j的MCP

序 本文主要研究一下langchain4j对Model Context Protocol (MCP) 的支持 MCP MCP协议规定了两种传输方式&#xff1a; HTTP&#xff1a;客户端请求一个SSE&#xff08;Server-Sent Events&#xff09;通道以从服务器接收事件&#xff0c;然后通过HTTP POST请求发送命令。这…...

我爱学算法之——滑动窗口攻克子数组和子串难题(中)

学习算法&#xff0c;继续加油&#xff01;&#xff01;&#xff01; 一、将 x 减到 0 的最小操作数 题目解析 来看这一道题&#xff0c;题目给定一个数组nums和一个整数x&#xff1b;我们可以在数组nums的左边或者右边进行操作&#xff08;x减去该位置的值&#xff09;&#…...

从零开始上手huggingface

1. 环境配置 # git 安装&#xff1a;https://git-scm.com/ # git lfs安装&#xff1a;https://git-lfs.com git lfs install # huggingface-cli 安装&#xff1a;https://huggingface.co/docs/hub/index pip install huggingface_hub2. 网站直接下载模型 可能会中断&#xff…...

MySQL 死锁问题分析与解决方案

**** 一、死锁原因分析 死锁通常由以下场景引发&#xff1a; 事务执行顺序不一致&#xff1a;多个事务以不同顺序访问相同资源。索引缺失&#xff1a;全表扫描导致行锁升级为表锁。长事务或大事务&#xff1a;长时间持有锁资源&#xff0c;增加冲突概率。隔离级别设置&#x…...

用 pytorch 从零开始创建大语言模型(六):对分类进行微调

用 pytorch 从零开始创建大语言模型&#xff08;六&#xff09;&#xff1a;对分类进行微调 6 微调用于分类6.1 微调的不同类别6.2 准备数据集6.3 创建数据加载器6.4 使用预训练权重初始化模型6.5 添加分类头部6.6 计算分类损失和准确率6.7 在监督数据上微调模型6.8 使用LLM进…...

dify1.1.1安装

1、 按照GitHub上操作 下载源码&#xff0c;没有安装git的&#xff0c;可以下载成zip包&#xff0c; unzip 解压 git clone https://github.com/langgenius/dify.git cd dify cd docker cp .env.example .env2、启动前 &#xff0c;先改下 docker-compose.yaml&#xff0c;…...

Netty——BIO、NIO 与 Netty

文章目录 1. 介绍1.1 BIO1.1.1 概念1.1.2 工作原理1.1.3 优缺点 1.2 NIO1.2.1 概念1.2.2 工作原理1.2.3 优缺点 1.3 Netty1.3.1 概念1.3.2 工作原理1.3.3 优点 2. Netty 与 Java NIO 的区别2.1 抽象层次2.2 API 易用性2.3 性能优化2.4 功能扩展性2.5 线程模型2.6 适用场景 3. 总…...

【Linux】信号:信号保存和处理

&#x1f525;个人主页&#xff1a;Quitecoder &#x1f525;专栏&#xff1a;linux笔记仓 目录 01.阻塞信号信号集 02.捕捉信号sigaction可重入函数volatileSIGCHLD 01.阻塞信号 实际执行信号的处理动作称为信号递达&#xff1a;每个信号都有一个默认行为&#xff0c;例如终…...

应用权限组列表

文章目录 使用须知位置相机麦克风通讯录日历运动数据身体传感器图片和视频音乐和音频跨应用关联设备发现和连接剪切板文件夹文件(deprecated) 使用须知 在申请目标权限前&#xff0c;建议开发者先阅读应用权限管控概述-权限组和子权限&#xff0c;了解相关概念&#xff0c;再合…...

MATLAB实现基于“蚁群算法”的AMR路径规划

目录 1 问题描述 2 算法理论 3 求解步骤 4 运行结果 5 代码部分 1 问题描述 移动机器人路径规划是机器人学的一个重要研究领域。它要求机器人依据某个或某些优化原则 (如最小能量消耗&#xff0c;最短行走路线&#xff0c;最短行走时间等)&#xff0c;在其工作空间中找到一…...

【深度学习】多目标融合算法(五):定制门控网络CGC(Customized Gate Control)

目录 一、引言 二、CGC&#xff08;Customized Gate Control&#xff0c;定制门控网络&#xff09; 2.1 技术原理 2.2 技术优缺点 2.3 业务代码实践 2.3.1 业务场景与建模 2.3.2 模型代码实现 2.3.3 模型训练与推理测试 2.3.4 打印模型结构 三、总结 一、引言 上一…...

【NLP 42、实践 ⑪ 用Bert模型结构实现自回归语言模型的训练】

如果结局早已注定&#xff0c;那么过程就将大于结局 —— 25.3.18 自回归语言模型&#xff1a;由前文预测后文的语言模型 特点&#xff1a;单向 训练方式&#xff1a;利用前n个字预测第n1个字&#xff0c;实现一个mask矩阵&#xff0c;送入Bert模型&#xff0c;让其前文看不到…...

TCP | 序列号和确认号 [逐包分析] | seq / ack 详解

注 &#xff1a; 本文为 “TCP 序号&#xff08;seq&#xff09;与确认序号&#xff08;ack&#xff09;” 相关文章合辑。 英文引文&#xff0c;机翻未校。 中文引文&#xff0c;略作重排。 如有内容异常&#xff0c;请看原文。 Understanding TCP Seq & Ack Numbers […...