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

如何使用GraphicsPath绘制形状创建自定义控件的Region以实现异形样式

问题排查与修正方案

核心错误点

  • 坐标定义错误:GetFigurePath 方法中 TopRight 点的Y值错误写成了 rect.Height,导致右上角点实际对齐到了矩形下边界,基础矩形形状完全错误。
  • 路径绘制逻辑错误:先绘制了完整闭合矩形,又额外添加右侧三角形路径,两段路径重叠冲突,闭合后生成的形状不符合预期。
  • 重绘逻辑错误:在 OnPaint 方法中修改 Size、BackColor、FlatStyle 等属性,这类属性变更会触发控件重绘,导致无限递归触发OnPaint,引发闪烁甚至卡顿。
  • 坐标范围错误:生成路径时使用固定的 DEFAULT_WIDTH、DEFAULT_HEIGHT,没有适配控件实际运行的尺寸,修改控件大小时样式会错乱。

修正后代码

路径生成方法

private GraphicsPath GetFigurePath(RectangleF rect)
{
    GraphicsPath path = new GraphicsPath();
    // 正确定义四个基础角点
    Point TopLeft = new Point((int)rect.X, (int)rect.Y);
    Point TopRight = new Point((int)rect.X + (int)rect.Width, (int)rect.Y);
    Point BottomLeft = new Point((int)rect.X, (int)rect.Y + (int)rect.Height);
    Point BottomRight = new Point((int)rect.X + (int)rect.Width, (int)rect.Y + (int)rect.Height);
    // 右侧箭头支点:矩形右侧外,垂直居中位置
    Point Fulcrum = new Point((int)rect.X + (int)rect.Width + (int)(rect.Height / 2), (int)(rect.Y + rect.Height / 2));

    path.StartFigure();
    // 按异形轮廓顺序绘制路径,无需额外画矩形
    path.AddLine(TopLeft, TopRight);
    path.AddLine(TopRight, Fulcrum);
    path.AddLine(Fulcrum, BottomRight);
    path.AddLine(BottomRight, BottomLeft);
    path.CloseFigure();

    return path;
}

重写OnPaint方法

// 相关样式属性建议移到构造函数中初始化,不要放在OnPaint里
public CustomNavLabel()
{
    this.FlatStyle = FlatStyle.Flat;
    this.Size = new Size(DEFAULT_WIDTH, DEFAULT_HEIGHT);
    this.BackColor = Color.Silver;
    this.ForeColor = Color.White;
    // 开启双缓冲防闪烁
    this.DoubleBuffered = true;
}

protected override void OnPaint(PaintEventArgs e)
{
    if (HasBorderStyle) {
        base.OnPaint(e);
        e.Graphics.SmoothingMode = SmoothingMode.AntiAlias;

        // 适配控件实际尺寸,不要用固定的DEFAULT宽高
        RectangleF rectSurface = new RectangleF(0, 0, this.Width - (int)(this.Height / 2), this.Height);
        RectangleF rectBorder = new RectangleF(1, 1, this.Width - (int)(this.Height / 2) - 2, this.Height - 2);

        using (GraphicsPath pathSurface = GetFigurePath(rectSurface))
        using (GraphicsPath pathBorder = GetFigurePath(rectBorder))
        using (Pen penSurface = new Pen(this.Parent.BackColor, 2))
        using (Pen penBorder = new Pen(borderColour, borderSize)) {
            penBorder.Alignment = PenAlignment.Inset;
            this.Region = new Region(pathSurface);
            e.Graphics.DrawPath(penSurface, pathSurface);
            e.Graphics.DrawPath(penBorder, pathBorder);
        }
    }
}

额外优化建议

  • 如果需要多个标签拼接无空隙,可调整箭头的凸出长度,适配相邻标签的左侧缩进。
  • 控件尺寸变更时可主动触发重绘,添加protected override void OnResize(EventArgs e) { base.OnResize(e); this.Invalidate(); } 确保尺寸修改时样式自动适配。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.05 15:18:02