You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.26 01:15:39