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

如何解决绘制圆弧时的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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.03 16:55:14