C#Winform 自定义透明按钮和单窗体模块化实现
技术看点
- WinForm自定义控件的使用
- WinForm单窗体应用如何模块化
需求及效果
又来一波 C# GDI自定义控件show 。这个控件已经使用几年了,最近找出来重构一下。原来是没有边框的,那么导致导航的功能不是很突出。本来想加个效果:在执行单击时显示Loading动画,在执行完单击事件后恢复原样。这就是网页里见到的局部刷新,Ajax常用的场景。无奈要下班了,还没弄出来。需求来自几年前一个智能储物柜项目,人机界面有个美工设计好的效果图,为了省事和通用,需要一个透明的按钮来实现导航的任务。就是控件只是设计时可见,运行时不可见。
关键点说明
1)、GraphicsPath实现矩形的圆角羽化处理
using (GraphicsPath path = new GraphicsPath()) { #region 羽化,圆角处理 path.StartFigure(); path.AddArc(new Rectangle(new Point(rect.X, rect.Y), new Size(2 * Radius, 2 * Radius)), 180, 90); path.AddLine(new Point(rect.X + Radius, rect.Y), new Point(rect.Right - Radius, rect.Y)); path.AddArc(new Rectangle(new Point(rect.Right - 2 * Radius, rect.Y), new Size(2 * Radius, 2 * Radius)), 270, 90); path.AddLine(new Point(rect.Right, rect.Y + Radius), new Point(rect.Right, rect.Bottom - Radius)); path.AddArc(new Rectangle(new Point(rect.Right - 2 * Radius, rect.Bottom - 2 * Radius), new Size(2 * Radius, 2 * Radius)), 0, 90); path.AddLine(new Point(rect.Right - Radius, rect.Bottom), new Point(rect.X + Radius, rect.Bottom)); path.AddArc(new Rectangle(new Point(rect.X, rect.Bottom - 2 * Radius), new Size(2 * Radius, 2 * Radius)), 90, 90); path.AddLine(new Point(rect.X, rect.Bottom - Radius), new Point(rect.X, rect.Y + Radius)); path.CloseFigure(); #endregion
要点就是画几段弧线和矩形连接起来。透明就是用了Color.FromArgb加上透明度,然后填充GraphicsPath形成透明区域。
g.FillPath(new SolidBrush(Color.FromArgb(153, BackColor)), path);
2)、单窗体应用如何模块化
窗体只有一个,但操作界面好多个,由于是无人值守的应用。那么老是切换窗体操作是非常不方便的。工作区域是一个容器Panel,把每个操作界面定义成一个Panel作为只容器。

public partial class DepositBizPanel : UserControl { private BackgroundStyle backgroundStyle = BackgroundStyle.Green; /// <summary> /// 主题风格 /// </summary> public BackgroundStyle BackgroundStyle { get { return backgroundStyle; } set { backgroundStyle = value; switch (value) { case GreenlandExpressBox.BackgroundStyle.Blue: BackgroundImage = Properties.Resources.jbblue; break; case GreenlandExpressBox.BackgroundStyle.Orange: BackgroundImage = Properties.Resources.jborange; break; case GreenlandExpressBox.BackgroundStyle.Green: BackgroundImage = Properties.Resources.jbgreen; break; } Invalidate(); } } public Panel ParentPanel { get; set; } public Bitmap QR_Barcode { get { return (Bitmap)pbxBarcode.Image; } set { pbxBarcode.Image = value; } } public DialogResult PanelDiagResult { get; set; } public DepositBizPanel(Panel parent, Bitmap barcode, BackgroundStyle style) { InitializeComponent(); DoubleBuffered = true; ParentPanel = parent; QR_Barcode = barcode; BackgroundStyle = style; } private void btnback_Click(object sender, EventArgs e) { foreach (Control panel in ParentPanel.Controls) { if (panel is DepositBizPanel) { ParentPanel.Controls.Remove(panel); PanelDiagResult = DialogResult.Cancel; break; } } } private void btnprocessnext_Click(object sender, EventArgs e) { foreach (Control panel in ParentPanel.Controls) { if (panel is DepositBizPanel) { ParentPanel.Controls.Remove(panel); PanelDiagResult = DialogResult.OK; break; } } } }
透明按钮自定义控件全部代码
自定义按钮:
/// <summary> /// Cool透明自定义按钮 /// </summary> public partial class CoolTransparentButton : UserControl { private Size iconSize = new Size(32, 32); public Size IconSize { get { return iconSize; } set { iconSize = value; Invalidate(); } } private string _ButtonText; public string ButtonText { get { return _ButtonText; } set { _ButtonText = value; Invalidate(); } } protected Image _IconImage; public Image IconImage { get { return _IconImage; } set { _IconImage = value; Invalidate(); } } private bool _FocseActived = false; private Color _BorderColor = Color.White; public Color BorderColor { get { return _BorderColor; } set { _BorderColor = value; Invalidate(); } } private int _Radius = 12; public int Radius { get { return _Radius; } set { _Radius = value; Invalidate(); } } private bool ifDrawBorderWhenLostFocse = true; /// <summary> /// 失去焦点是否画边框 /// </summary> public bool IfDrawBorderWhenLostFocse { get { return ifDrawBorderWhenLostFocse; } set { ifDrawBorderWhenLostFocse = value; Invalidate(); } } /// <summary> /// 是否处于激活状态(焦点) /// </summary> public bool FocseActived { get { return _FocseActived; } set { _FocseActived = value; Invalidate(); } } public CoolTransparentButton() { DoubleBuffered = true; BackColor = Color.Transparent; SetStyle(ControlStyles.AllPaintingInWmPaint | ControlStyles.OptimizedDoubleBuffer | ControlStyles.ResizeRedraw, true); SetStyle(ControlStyles.Opaque, false); UpdateStyles(); } protected override void OnPaint(PaintEventArgs e) { var rect = ClientRectangle; rect.Inflate(-1, -1); Graphics g = e.Graphics; g.SmoothingMode = SmoothingMode.HighQuality; using (GraphicsPath path = new GraphicsPath()) { #region 羽化,圆角处理 path.StartFigure(); path.AddArc(new Rectangle(new Point(rect.X, rect.Y), new Size(2 * Radius, 2 * Radius)), 180, 90); path.AddLine(new Point(rect.X + Radius, rect.Y), new Point(rect.Right - Radius, rect.Y)); path.AddArc(new Rectangle(new Point(rect.Right - 2 * Radius, rect.Y), new Size(2 * Radius, 2 * Radius)), 270, 90); path.AddLine(new Point(rect.Right, rect.Y + Radius), new Point(rect.Right, rect.Bottom - Radius)); path.AddArc(new Rectangle(new Point(rect.Right - 2 * Radius, rect.Bottom - 2 * Radius), new Size(2 * Radius, 2 * Radius)), 0, 90); path.AddLine(new Point(rect.Right - Radius, rect.Bottom), new Point(rect.X + Radius, rect.Bottom)); path.AddArc(new Rectangle(new Point(rect.X, rect.Bottom - 2 * Radius), new Size(2 * Radius, 2 * Radius)), 90, 90); path.AddLine(new Point(rect.X, rect.Bottom - Radius), new Point(rect.X, rect.Y + Radius)); path.CloseFigure(); #endregion if (!FocseActived) { if (ifDrawBorderWhenLostFocse) g.DrawPath(new Pen(Color.Gray, 1), path); g.FillPath(new SolidBrush(Color.FromArgb(66, BackColor)), path); } else { g.DrawPath(new Pen(BorderColor, 1), path); rect.Inflate(-1, -1); g.FillPath(new SolidBrush(Color.FromArgb(153, BackColor)), path); } #region 画文本 g.SmoothingMode = SmoothingMode.AntiAlias; if (IconImage != null) { Rectangle rc = new Rectangle((Width - 32) / 2, 16, IconSize.Width, IconSize.Height); g.DrawImage(IconImage, rc); } if (!string.IsNullOrEmpty(ButtonText)) { using (StringFormat f = new StringFormat()) { Rectangle rectTxt = new Rectangle(0, (Height - 18) / 2, Width, 36); f.Alignment = StringAlignment.Center;// 水平居中对齐 f.LineAlignment = StringAlignment.Center; // 垂直居中对齐 f.FormatFlags = StringFormatFlags.NoWrap;// 设置为单行文本 SolidBrush fb = new SolidBrush(this.ForeColor); // 绘制文本 e.Graphics.DrawString(ButtonText, new Font("微软雅黑", 16F, FontStyle.Bold), fb, rectTxt, f); } } #endregion } } protected override void OnMouseHover(EventArgs e) { FocseActived = true; } protected override void OnMouseLeave(EventArgs e) { FocseActived = false; } protected override void OnEnter(EventArgs e) { FocseActived = true; } protected override void OnLeave(EventArgs e) { FocseActived = false; } }
注释不是很多,如有需要拿走不谢.
作者:数据酷软件
出处:https://www.cnblogs.com/datacool/p/datacool_2017_transBtn.html
关于作者:20年编程从业经验,持续关注MES/ERP/POS/WMS/工业自动化
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明。
联系方式: qq:71008973;wx:6857740733
基于人脸识别的考勤系统 地址: https://gitee.com/afeng124/viewface_attendance_ext
自己开发安卓应用框架 地址: https://gitee.com/afeng124/android-app-frame
WPOS(warehouse+pos) 后台演示地址: http://47.239.106.75:8080/
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?