C# 中 GDI+ 实现圆角窗体设计

257 阅读4分钟

前言

用户界面的美观性和个性化程度越来越受到重视。传统的矩形窗体已无法满足某些特定项目对视觉效果的需求。使用 C# 和 GDI+ 技术,我们可以轻松实现自定义窗体样式,其中 圆角窗体(Rounded Form) 是一个经典且实用的案例。

本文将从原理讲解到代码实现,全面介绍如何使用 C# 的 GDI+ 绘图技术打造一个支持圆角、边框、背景色、拖动功能以及阴影效果的 WinForms 自定义窗体,并提供完整的代码示例与使用注意事项。

正文

一、实现原理

圆角窗体的核心在于对窗体外观的完全自定义绘制。其实现主要依赖以下关键技术点:

1、GraphicsPath 创建圆角路径:用于定义窗体的形状。

2、Region 设置窗体区域:通过设置窗体的 Region 属性,使其显示为圆角形状。

3、重写 OnPaint 方法:实现自定义绘图逻辑,包括背景填充和边框绘制。

4、实现窗体拖动功能:通过鼠标事件控制窗体移动。

5、添加阴影效果:利用 Windows API 实现窗体阴影。

二、完整代码实现

1、创建基础窗体类

using System;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Windows.Forms;

public class RoundedForm : Form
{
    // 圆角半径
    private int cornerRadius = 20;
    // 窗体边框颜色
    private Color borderColor = Color.FromArgb(100, 100, 100);
    // 窗体背景色
    private Color backgroundColor = Color.White;

    public RoundedForm()
    {
        // 设置窗体基本属性
        this.FormBorderStyle = FormBorderStyle.None;
        this.DoubleBuffered = true;
        this.SetStyle(ControlStyles.ResizeRedraw | ControlStyles.OptimizedDoubleBuffer | ControlStyles.AllPaintingInWmPaint, true);
        this.Size = new Size(800, 500);
    }

    // 属性:圆角半径
    public int CornerRadius
    {
        get { return cornerRadius; }
        set
        {
            cornerRadius = value;
            this.Invalidate();
        }
    }

    // 属性:边框颜色
    public Color BorderColor
    {
        get { return borderColor; }
        set
        {
            borderColor = value;
            this.Invalidate();
        }
    }

    // 属性:背景颜色
    public Color BackgroundColor
    {
        get { return backgroundColor; }
        set
        {
            backgroundColor = value;
            this.Invalidate();
        }
    }
}

2、实现圆角路径创建方法

private GraphicsPath CreateRoundedPath(Rectangle rect, int radius)
{
    GraphicsPath path = new GraphicsPath();
    radius = Math.Min(radius, Math.Min(rect.Width / 2, rect.Height / 2));
    int diameter = radius * 2;
    Rectangle arcRect = new Rectangle(rect.Location, new Size(diameter, diameter));

    // 左上角
    path.AddArc(arcRect.X, arcRect.Y, diameter, diameter, 180, 90);
    // 右上角
    arcRect.X = rect.Right - diameter;
    path.AddArc(arcRect.X, arcRect.Y, diameter, diameter, 270, 90);
    // 右下角
    arcRect.Y = rect.Bottom - diameter;
    path.AddArc(arcRect.X, arcRect.Y, diameter, diameter, 0, 90);
    // 左下角
    arcRect.X = rect.Left;
    path.AddArc(arcRect.X, arcRect.Y, diameter, diameter, 90, 90);

    path.CloseFigure();
    return path;
}

3、重写 OnPaint 方法实现自定义绘制

protected override void OnPaint(PaintEventArgs e)
{
    base.OnPaint(e);
    Graphics g = e.Graphics;
    g.SmoothingMode = SmoothingMode.AntiAlias;
    g.InterpolationMode = InterpolationMode.HighQualityBicubic;
    g.CompositingQuality = CompositingQuality.HighQuality;

    Rectangle rect = new Rectangle(0, 0, this.Width - 1, this.Height - 1);

    using (GraphicsPath path = CreateRoundedPath(rect, cornerRadius))
    {
        this.Region = new Region(path);

        using (SolidBrush brush = new SolidBrush(backgroundColor))
        {
            g.FillPath(brush, path);
        }

        using (Pen pen = new Pen(borderColor, 1.0f))
        {
            pen.Alignment = PenAlignment.Inset;
            pen.EndCap = LineCap.Round;
            pen.StartCap = LineCap.Round;
            pen.LineJoin = LineJoin.Round;
            g.DrawPath(pen, path);
        }
    }
}

4、实现窗体拖动功能

private bool isDragging = false;
private Point lastLocation;

protected override void OnMouseDown(MouseEventArgs e)
{
    base.OnMouseDown(e);
    if (e.Button == MouseButtons.Left)
    {
        isDragging = true;
        lastLocation = e.Location;
    }
}

protected override void OnMouseMove(MouseEventArgs e)
{
    base.OnMouseMove(e);
    if (isDragging)
    {
        this.Location = new Point(
            (this.Location.X - lastLocation.X) + e.X,
            (this.Location.Y - lastLocation.Y) + e.Y
        );
    }
}

protected override void OnMouseUp(MouseEventArgs e)
{
    base.OnMouseUp(e);
    isDragging = false;
}

5、添加窗体阴影效果

private bool enableShadow = true;
private const int CS_DROPSHADOW = 0x20000;

protected override CreateParams CreateParams
{
    get
    {
        CreateParams cp = base.CreateParams;
        if (enableShadow)
        {
            cp.ClassStyle |= CS_DROPSHADOW;
        }
        return cp;
    }
}

// 启用/禁用阴影
public bool EnableShadow
{
    get { return enableShadow; }
    set
    {
        enableShadow = value;
        this.RecreateHandle();
    }
}

6、示例使用代码

[STAThread]
static void Main()
{
    Application.EnableVisualStyles();
    Application.SetCompatibleTextRenderingDefault(false);

    RoundedForm form = new RoundedForm();
    form.CornerRadius = 20;
    form.BorderColor = Color.FromArgb(64, 64, 64);
    form.BackgroundColor = Color.White;

    Button closeButton = new Button();
    closeButton.Text = "关闭";
    closeButton.Location = new Point(form.Width - 100, 20);
    closeButton.Click += (s, e) => form.Close();
    form.Controls.Add(closeButton);

    Application.Run(form);
}

效果

注意事项

1、性能优化建议

启用双缓冲 (DoubleBuffered) 避免画面闪烁;

控制圆角半径大小,避免过大影响性能;

注意及时释放 GDI+ 资源,如 GraphicsPathPenBrush

对于复杂绘制,可考虑异步渲染或局部刷新。

2、常见问题及解决办法

窗体出现锯齿:检查是否启用了抗锯齿(SmoothingMode.AntiAlias);

拖动不流畅:优化鼠标事件处理逻辑;

控件超出圆角范围:合理设置控件位置或限制布局;

阴影未生效:确认操作系统支持阴影效果(部分系统需启用 DWM)。

总结

通过本文的详细介绍和完整代码实现,我们了解了如何使用 C# 和 GDI+ 开发一个具有圆角、边框、背景色、拖动功能和阴影效果的自定义 WinForm 窗体。该技术不仅提升了应用的视觉表现力,也为后续更复杂的 UI 定制打下了良好基础。

不管用于制作登录界面、弹出窗口还是现代风格的应用程序,圆角窗体都是一种简单而有效的美化手段。希望本文能帮助大家掌握这一实用技能,在实际项目中灵活运用!

最后

如果你觉得这篇文章对你有帮助,不妨点个赞支持一下!你的支持是我继续分享知识的动力。如果有任何疑问或需要进一步的帮助,欢迎随时留言。

也可以加入微信公众号 [DotNet技术匠] 社区,与其他热爱技术的同行一起交流心得,共同成长!

优秀是一种习惯,欢迎大家留言学习!

作者:技术老小子

出处:mp.weixin.qq.com/s/K6c99pho4q-S_yl1zvGCPA

声明:网络内容,仅供学习,尊重版权,侵权速删,歉意致谢!