如何在Windows 10的.NET 8 WinForms中创建Windows XP风格按钮
实现Windows XP风格的WinForms按钮(.NET 8,Win10)
当然可以实现类似XP风格的圆角+悬浮/点击弹出效果的按钮,WinForms默认样式受系统主题限制,但通过自定义控件重绘就能搞定,完全不需要依赖第三方库,以下是具体实现步骤:
自定义控件实现方案(C#示例)
1. 创建自定义Button类
继承原生Button,重绘外观并处理鼠标交互事件,实现圆角、悬浮凸起、按下凹陷的效果:
using System.Drawing; using System.Windows.Forms; public class XPButton : Button { private bool _isHovered; private bool _isPressed; public XPButton() { // 基础配置:关闭默认边框、开启双缓冲防闪烁 FlatStyle = FlatStyle.Flat; FlatAppearance.BorderSize = 0; DoubleBuffered = true; Size = new Size(100, 30); BackColor = Color.FromArgb(236, 233, 216); // XP按钮基础底色 ForeColor = Color.Black; } // 鼠标进入时标记悬浮状态 protected override void OnMouseEnter(System.EventArgs e) { _isHovered = true; Invalidate(); // 触发控件重绘 base.OnMouseEnter(e); } // 鼠标离开时重置状态 protected override void OnMouseLeave(System.EventArgs e) { _isHovered = false; _isPressed = false; Invalidate(); base.OnMouseLeave(e); } // 鼠标按下时标记按压状态 protected override void OnMouseDown(MouseEventArgs e) { if (e.Button == MouseButtons.Left) { _isPressed = true; Invalidate(); } base.OnMouseDown(e); } // 鼠标松开时重置按压状态 protected override void OnMouseUp(MouseEventArgs e) { _isPressed = false; Invalidate(); base.OnMouseUp(e); } // 核心重绘逻辑 protected override void OnPaint(PaintEventArgs pevent) { var g = pevent.Graphics; g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias; // 开启抗锯齿,让圆角更顺滑 var rect = new Rectangle(0, 0, Width - 1, Height - 1); // 绘制圆角背景 using (var bgBrush = new SolidBrush(_isPressed ? Color.FromArgb(200, 197, 180) : _isHovered ? Color.FromArgb(245, 242, 225) : BackColor)) using (var path = new System.Drawing.Drawing2D.GraphicsPath()) { int cornerRadius = 6; // XP风格按钮的圆角大小 path.AddArc(rect.X, rect.Y, cornerRadius, cornerRadius, 180, 90); path.AddArc(rect.X + rect.Width - cornerRadius, rect.Y, cornerRadius, cornerRadius, 270, 90); path.AddArc(rect.X + rect.Width - cornerRadius, rect.Y + rect.Height - cornerRadius, cornerRadius, cornerRadius, 0, 90); path.AddArc(rect.X, rect.Y + rect.Height - cornerRadius, cornerRadius, cornerRadius, 90, 90); path.CloseAllFigures(); g.FillPath(bgBrush, path); // 绘制边框和凸起/凹陷效果 using (var borderPen = new Pen(Color.FromArgb(100, 100, 100))) { if (_isPressed) { // 按下时的凹陷效果:白色右下边框,深灰主边框 g.DrawPath(borderPen, path); g.DrawLine(new Pen(Color.White), rect.X + 1, rect.Y + rect.Height - 1, rect.X + rect.Width - 1, rect.Y + rect.Height - 1); g.DrawLine(new Pen(Color.White), rect.X + rect.Width - 1, rect.Y + 1, rect.X + rect.Width - 1, rect.Y + rect.Height - 1); } else { // 正常/悬浮时的凸起效果:白色左上边框,深灰主边框 g.DrawLine(new Pen(Color.White), rect.X + 1, rect.Y, rect.X + rect.Width - 2, rect.Y); g.DrawLine(new Pen(Color.White), rect.X, rect.Y + 1, rect.X, rect.Y + rect.Height - 2); g.DrawPath(borderPen, path); } } } // 绘制按钮文本 var textRect = new Rectangle(0, 0, Width, Height); var format = new StringFormat { Alignment = StringAlignment.Center, LineAlignment = StringAlignment.Center }; g.DrawString(Text, Font, new SolidBrush(ForeColor), textRect, format); } }
2. 在设计器中使用自定义按钮
编译项目后,XPButton会自动出现在Visual Studio工具箱的自定义控件分类里,直接拖拽到窗体即可使用,也可以通过代码实例化:
var xpBtn = new XPButton(); xpBtn.Text = "XP风格按钮"; xpBtn.Location = new Point(50, 50); this.Controls.Add(xpBtn);
VB.NET版本简化实现
Imports System.Drawing Imports System.Windows.Forms Public Class XPButton Inherits Button Private _isHovered As Boolean Private _isPressed As Boolean Public Sub New() FlatStyle = FlatStyle.Flat FlatAppearance.BorderSize = 0 DoubleBuffered = True Size = New Size(100, 30) BackColor = Color.FromArgb(236, 233, 216) ForeColor = Color.Black End Sub Protected Overrides Sub OnMouseEnter(e As EventArgs) _isHovered = True Invalidate() MyBase.OnMouseEnter(e) End Sub Protected Overrides Sub OnMouseLeave(e As EventArgs) _isHovered = False _isPressed = False Invalidate() MyBase.OnMouseLeave(e) End Sub Protected Overrides Sub OnMouseDown(e As MouseEventArgs) If e.Button = MouseButtons.Left Then _isPressed = True Invalidate() End If MyBase.OnMouseDown(e) End Sub Protected Overrides Sub OnMouseUp(e As MouseEventArgs) _isPressed = False Invalidate() MyBase.OnMouseUp(e) End Sub Protected Overrides Sub OnPaint(pevent As PaintEventArgs) Dim g = pevent.Graphics g.SmoothingMode = Drawing2D.SmoothingMode.AntiAlias Dim rect = New Rectangle(0, 0, Width - 1, Height - 1) Using bgBrush As New SolidBrush(If(_isPressed, Color.FromArgb(200, 197, 180), If(_isHovered, Color.FromArgb(245, 242, 225), BackColor))) Using path As New Drawing2D.GraphicsPath() Dim cornerRadius = 6 path.AddArc(rect.X, rect.Y, cornerRadius, cornerRadius, 180, 90) path.AddArc(rect.X + rect.Width - cornerRadius, rect.Y, cornerRadius, cornerRadius, 270, 90) path.AddArc(rect.X + rect.Width - cornerRadius, rect.Y + rect.Height - cornerRadius, cornerRadius, cornerRadius, 0, 90) path.AddArc(rect.X, rect.Y + rect.Height - cornerRadius, cornerRadius, cornerRadius, 90, 90) path.CloseAllFigures() g.FillPath(bgBrush, path) Using borderPen As New Pen(Color.FromArgb(100, 100, 100)) If _isPressed Then g.DrawPath(borderPen, path) g.DrawLine(New Pen(Color.White), rect.X + 1, rect.Y + rect.Height - 1, rect.X + rect.Width - 1, rect.Y + rect.Height - 1) g.DrawLine(New Pen(Color.White), rect.X + rect.Width - 1, rect.Y + 1, rect.X + rect.Width - 1, rect.Y + rect.Height - 1) Else g.DrawLine(New Pen(Color.White), rect.X + 1, rect.Y, rect.X + rect.Width - 2, rect.Y) g.DrawLine(New Pen(Color.White), rect.X, rect.Y + 1, rect.X, rect.Y + rect.Height - 2) g.DrawPath(borderPen, path) End If End Using End Using End Using Dim textRect = New Rectangle(0, 0, Width, Height) Dim format As New StringFormat() With { .Alignment = StringAlignment.Center, .LineAlignment = StringAlignment.Center } g.DrawString(Text, Font, New SolidBrush(ForeColor), textRect, format) End Sub End Class
额外优化建议
- 可以给自定义按钮添加可配置属性(比如圆角大小、主题颜色),方便在设计器中直接调整
- 若需要更贴近XP原生效果,可微调颜色值和边框绘制的细节(比如XP按钮的阴影是浅灰左上、深灰右下)
- 保持
DoubleBuffered = true避免重绘时的闪烁问题
内容的提问来源于stack exchange,提问作者Rahul.In
相关产品推荐
相关产品推荐

