如何解决绘制圆弧时的ArgumentException:参数无效问题
解决WinForms自定义按钮FillPath/DrawPath参数无效问题
问题根源分析
触发ArgumentException: 参数无效的核心原因如下:
- 变量拼写混乱:代码混用
Roundenes和_Roundnes,导致圆角参数计算错误 - 矩形参数非法:AddArc使用的矩形宽/高可能为0或负数,或坐标超出控件范围
- 路径衔接错误:线条与圆弧的起点/终点不匹配,形成无效路径区域
- Paint事件重复创建控件:每次重绘都生成新Label,引发控件堆积和逻辑混乱
分步修复方案
1. 统一变量命名
将所有Roundenes替换为_Roundnes,避免参数引用错误:
' 修正前 If PathHeight < Roundenes.Height Then _Roundnes.Height = PathHeight - 1 End If ' 修正后 If PathHeight < _Roundnes.Height Then _Roundnes.Height = PathHeight - 1 End If
2. 确保圆角参数合法
强制限制圆角宽高为正整数,避免AddArc传入无效矩形:
_Roundnes.Width = Math.Max(1, _Roundnes.Width) _Roundnes.Height = Math.Max(1, _Roundnes.Height)
3. 修正路径计算逻辑
重新计算路径坐标,确保线条与圆弧完美衔接:
' 修正PathWidth/PathHeight:左右/上下各留BorderSize/2,总宽度减去BorderSize Dim PathWidth As Integer = Width - BorderSize Dim PathHeight As Integer = Height - BorderSize ' 修正四个圆角矩形坐标 Dim Rec1 As New Rectangle(BorderSize \ 2, BorderSize \ 2, _Roundnes.Width, _Roundnes.Height) Dim Rec2 As New Rectangle(PathWidth - _Roundnes.Width + BorderSize \ 2, BorderSize \ 2, _Roundnes.Width, _Roundnes.Height) Dim Rec3 As New Rectangle(PathWidth - _Roundnes.Width + BorderSize \ 2, PathHeight - _Roundnes.Height + BorderSize \ 2, _Roundnes.Width, _Roundnes.Height) Dim Rec4 As New Rectangle(BorderSize \ 2, PathHeight - _Roundnes.Height + BorderSize \ 2, _Roundnes.Width, _Roundnes.Height) ' 重构路径衔接逻辑 OuterPath.StartFigure() ' 顶部线条:左上角圆弧终点 → 右上角圆弧起点 OuterPath.AddLine(Rec1.X + _Roundnes.Width \ 2, Rec1.Y, Rec2.X + _Roundnes.Width \ 2, Rec2.Y) ' 左上角圆弧:180° → 270°(顺时针) OuterPath.AddArc(Rec1, 180, 90) ' 左侧线条:左上角圆弧起点 → 左下角圆弧终点 OuterPath.AddLine(Rec1.X, Rec1.Y + _Roundnes.Height \ 2, Rec4.X, Rec4.Y + _Roundnes.Height \ 2) ' 左下角圆弧:90° → 180° OuterPath.AddArc(Rec4, 90, 90) ' 底部线条:左下角圆弧起点 → 右下角圆弧终点 OuterPath.AddLine(Rec4.X + _Roundnes.Width \ 2, Rec4.Y + _Roundnes.Height, Rec3.X + _Roundnes.Width \ 2, Rec3.Y + _Roundnes.Height) ' 右下角圆弧:0° → 90° OuterPath.AddArc(Rec3, 0, 90) ' 右侧线条:右下角圆弧起点 → 右上角圆弧终点 OuterPath.AddLine(Rec3.X + _Roundnes.Width, Rec3.Y + _Roundnes.Height \ 2, Rec2.X + _Roundnes.Width, Rec2.Y + _Roundnes.Height \ 2) ' 右上角圆弧:270° → 360° OuterPath.AddArc(Rec2, 270, 90) OuterPath.CloseFigure()
4. 优化控件创建逻辑
避免在Paint事件中重复添加Label,改为构造函数初始化,Paint事件仅更新属性:
' 控件构造函数中创建文本标签 Public Sub New() InitializeComponent() Dim TextPlace As New Label With { .Name = "TextLabel", .AutoEllipsis = True, .TextAlign = _TextAlign, .ForeColor = _FontColor, .BackColor = _MetaniumBackColor } AddHandler TextPlace.TextChanged, AddressOf MetaniumButton_TextChanged AddHandler Me.TextChanged, AddressOf MetaniumButton_TextChanged Controls.Add(TextPlace) End Sub ' Paint事件中仅更新标签属性 Private Sub MetaniumButton_Paint(sender As Object, e As PaintEventArgs) Handles Me.Paint ' ... 路径绘制代码 ... Dim TextPlace = DirectCast(Controls.Find("TextLabel", True)(0), Label) TextPlace.Text = Text TextPlace.Size = New Size(Width - (Margin.Left + Margin.Right + _Roundnes.Width), Height - (Margin.Top + Margin.Bottom + _Roundnes.Height)) TextPlace.Location = New Point((Width - TextPlace.Width) \ 2, (Height - TextPlace.Height) \ 2) End Sub
5. 释放GraphicsPath资源
使用Using语句避免资源泄漏:
Using OuterPath As New GraphicsPath() ' ... 路径构建代码 ... e.Graphics.FillPath(Brush1, OuterPath) e.Graphics.DrawPath(Pen1, OuterPath) End Using
完整修正后的核心Paint代码
Private Sub MetaniumButton_Paint(sender As Object, e As PaintEventArgs) Handles Me.Paint e.Graphics.SmoothingMode = Drawing2D.SmoothingMode.AntiAlias Dim BorderSize As Integer = ' 替换为你的边框大小变量 _Roundnes = RoundnesMemory ' 计算路径尺寸 Dim PathWidth As Integer = Width - BorderSize Dim PathHeight As Integer = Height - BorderSize ' 修正圆角参数 If PathHeight < _Roundnes.Height Then _Roundnes.Height = PathHeight - 1 End If If PathWidth < _Roundnes.Width Then _Roundnes.Width = PathWidth - 1 End If _Roundnes.Width = Math.Max(1, _Roundnes.Width) _Roundnes.Height = Math.Max(1, _Roundnes.Height) ' 构建并绘制路径 Using OuterPath As New GraphicsPath() Dim Rec1 As New Rectangle(BorderSize \ 2, BorderSize \ 2, _Roundnes.Width, _Roundnes.Height) Dim Rec2 As New Rectangle(PathWidth - _Roundnes.Width + BorderSize \ 2, BorderSize \ 2, _Roundnes.Width, _Roundnes.Height) Dim Rec3 As New Rectangle(PathWidth - _Roundnes.Width + BorderSize \ 2, PathHeight - _Roundnes.Height + BorderSize \ 2, _Roundnes.Width, _Roundnes.Height) Dim Rec4 As New Rectangle(BorderSize \ 2, PathHeight - _Roundnes.Height + BorderSize \ 2, _Roundnes.Width, _Roundnes.Height) OuterPath.StartFigure() OuterPath.AddLine(Rec1.X + _Roundnes.Width \ 2, Rec1.Y, Rec2.X + _Roundnes.Width \ 2, Rec2.Y) OuterPath.AddArc(Rec1, 180, 90) OuterPath.AddLine(Rec1.X, Rec1.Y + _Roundnes.Height \ 2, Rec4.X, Rec4.Y + _Roundnes.Height \ 2) OuterPath.AddArc(Rec4, 90, 90) OuterPath.AddLine(Rec4.X + _Roundnes.Width \ 2, Rec4.Y + _Roundnes.Height, Rec3.X + _Roundnes.Width \ 2, Rec3.Y + _Roundnes.Height) OuterPath.AddArc(Rec3, 0, 90) OuterPath.AddLine(Rec3.X + _Roundnes.Width, Rec3.Y + _Roundnes.Height \ 2, Rec2.X + _Roundnes.Width, Rec2.Y + _Roundnes.Height \ 2) OuterPath.AddArc(Rec2, 270, 90) OuterPath.CloseFigure() e.Graphics.FillPath(Brush1, OuterPath) e.Graphics.DrawPath(Pen1, OuterPath) End Using ' 更新文本标签 Dim TextPlace = DirectCast(Controls.Find("TextLabel", True)(0), Label) TextPlace.Text = Text TextPlace.Size = New Size(Width - (Margin.Left + Margin.Right + _Roundnes.Width), Height - (Margin.Top + Margin.Bottom + _Roundnes.Height)) TextPlace.Location = New Point((Width - TextPlace.Width) \ 2, (Height - TextPlace.Height) \ 2) End Sub
内容的提问来源于stack exchange,提问作者Bendouba Abdessalem
相关产品推荐
相关产品推荐

