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空引用错误
问题根源
- 构造函数访问权限错误:自定义按钮的构造函数是私有的,导致设计器或代码无法创建实例,字段自然为null。
- 重复调用基类方法:
OnHandleCreated里重复执行了base.OnHandleCreated(e);,虽不致命但属于冗余代码。 - 未判空的父容器访问:
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
相关产品推荐
相关产品推荐

