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

C#自定义圆角Button控件报错:对象引用未设置为实例

解决自定义圆角按钮的空引用错误与未赋值警告

问题说明

我实现了一个继承自Button的CustomButton类来做圆角按钮,但使用时遇到两个问题:

  • 编译警告:Field 'frmMainPanel.customButton1' is never assigned to, and will always have its default value null
  • 运行时抛出Object reference not set to an instance of an object空引用错误

问题根源

  1. 构造函数访问权限错误:自定义按钮的构造函数是私有的,导致设计器或代码无法创建实例,字段自然为null。
  2. 重复调用基类方法:OnHandleCreated里重复执行了base.OnHandleCreated(e);,虽不致命但属于冗余代码。
  3. 未判空的父容器访问:OnPaint中直接使用this.Parent.BackColor,如果按钮还没添加到父容器,Parent会是null,触发空引用。

修复方案

1. 修正构造函数访问修饰符

将构造函数改为公共,允许外部实例化:

public CustomButton()
{
    this.FlatStyle = FlatStyle.Flat;
    this.FlatAppearance.BorderSize = 0;
    this.Size = new Size(150,40);
    this.BackColor = Color.MediumSlateBlue;
    this.ForeColor = Color.White;
}

2. 清理OnHandleCreated的冗余代码

去掉重复的基类方法调用:

protected override void OnHandleCreated(EventArgs e)
{
    base.OnHandleCreated(e);
    this.Parent.BackColorChanged += Container_BackColorChanged;
}

3. 给Parent访问添加空保护

在OnPaint中使用空合并运算符处理Parent为空的情况:

using (Pen penSurface = new Pen(this.Parent?.BackColor ?? Color.White, 2))

完整修复后的代码

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

public class CustomButton : Button
{
    // Fields
    private int borderSize = 0;
    private int borderRadius = 40;
    private Color borderColor = Color.PaleVioletRed;

    [Category("Custom Controls")]
    public int BorderSize
    {
        get => borderSize;
        set
        {
            borderSize = value;
            Invalidate();
        }
    }

    [Category("Custom Controls")]
    public int BorderRadius
    {
        get => borderRadius;
        set
        {
            borderRadius = value;
            Invalidate();
        }
    }

    [Category("Custom Controls")]
    public Color BorderColor
    {
        get => borderColor;
        set
        {
            borderColor = value;
            Invalidate();
        }
    }

    [Category("Custom Controls")]
    public Color TextColor
    {
        get => ForeColor;
        set => ForeColor = value;
    }

    // Constructor - 修改为公共访问
    public CustomButton()
    {
        FlatStyle = FlatStyle.Flat;
        FlatAppearance.BorderSize = 0;
        Size = new Size(150, 40);
        BackColor = Color.MediumSlateBlue;
        ForeColor = Color.White;
    }

    // Methods
    private GraphicsPath GetFigurePath(RectangleF rect, float radius)
    {
        GraphicsPath path = new GraphicsPath();
        path.StartFigure();
        path.AddArc(rect.X, rect.Y, radius, radius, 180, 90);
        path.AddArc(rect.Width - radius, rect.Y, radius, radius, 270, 90);
        path.AddArc(rect.Width - radius, rect.Height - radius, radius, radius, 0, 90);
        path.AddArc(rect.X, rect.Height - radius, radius, radius, 90, 90);
        path.CloseFigure();
        return path;
    }

    protected override void OnPaint(PaintEventArgs pevent)
    {
        base.OnPaint(pevent);
        pevent.Graphics.SmoothingMode = SmoothingMode.AntiAlias;
        RectangleF rectSurface = new RectangleF(0, 0, Width, Height);
        RectangleF rectBorder = new RectangleF(1, 1, Width - 0.8F, Height - 1);

        if (borderRadius > 2) // Rounded Button
        {
            using (GraphicsPath pathSurface = GetFigurePath(rectSurface, borderRadius))
            using (GraphicsPath pathBorder = GetFigurePath(rectBorder, borderRadius - 1F))
            // 增加Parent空判断,备用颜色设为White
            using (Pen penSurface = new Pen(Parent?.BackColor ?? Color.White, 2))
            using (Pen penBorder = new Pen(borderColor, borderSize))
            {
                penBorder.Alignment = PenAlignment.Inset;
                Region = new Region(pathSurface);
                pevent.Graphics.DrawPath(penBorder, pathBorder);

                if (borderSize >= 1)
                    pevent.Graphics.DrawPath(penBorder, pathBorder);
            }
        }
        else // Normal Button
        {
            Region = new Region(rectSurface);
            if (borderSize >= 1)
            {
                using (Pen penBorder = new Pen(borderColor, borderSize))
                {
                    penBorder.Alignment = PenAlignment.Inset;
                    pevent.Graphics.DrawRectangle(penBorder, 0, 0, Width - 1, Height - 1);
                }
            }
        }
    }

    protected override void OnHandleCreated(EventArgs e)
    {
        base.OnHandleCreated(e);
        Parent.BackColorChanged += Container_BackColorChanged;
    }

    private void Container_BackColorChanged(object sender, EventArgs e)
    {
        if (DesignMode)
            Invalidate();
    }

    private void InitializeComponent()
    {
        SuspendLayout();
        ResumeLayout(false);
    }
}

解决未赋值警告

  • 如果用设计器添加控件:确保从工具箱中拖放CustomButton到窗体上,设计器会自动完成实例化和字段赋值。
  • 如果手动代码创建:必须显式实例化并添加到窗体控件集合:
// 在窗体构造函数或Load事件中添加
CustomButton customButton1 = new CustomButton();
customButton1.Location = new Point(50, 50);
customButton1.Text = "圆角按钮";
this.Controls.Add(customButton1);

内容的提问来源于stack exchange,提问作者ash vaaz

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.14 05:06:02