winforms 如何填充弧?

1zmg4dgp  于 2022-11-30  发布在  其他
关注(0)|答案(1)|浏览(170)

我想做的是创建这个旋转圆锥体的视觉效果,就像我几年前做的那样,但没有使用direct。回到那个时候,我使用了一个非常旧的directx dll文件。

到目前为止,我已经尝试过:
即使IM将刻度改变为50或更大,电弧仍然没有被填充。

public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();

            pictureBox1.Invalidate();
        }

        private void pictureBox1_Paint(object sender, PaintEventArgs e)
        {
            var g = e.Graphics;
            g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;

            var center = new Point(pictureBox1.Width / 2, pictureBox1.Height / 2);
            var innerR = 30;
            var thickness = 20;
            var startAngle = 0;
            var arcLength = 360;
            var outerR = innerR + thickness;
            var outerRect = new Rectangle
                            (center.X - outerR, center.Y - outerR, 2 * outerR, 2 * outerR);
            var innerRect = new Rectangle
                            (center.X - innerR, center.Y - innerR, 2 * innerR, 2 * innerR);

            using (var p = new GraphicsPath())
            {
                p.AddArc(outerRect, startAngle, arcLength);
                p.AddArc(innerRect, startAngle + arcLength, -arcLength);
                p.CloseFigure();
                e.Graphics.FillPath(Brushes.Green, p);
                e.Graphics.DrawPath(Pens.Green, p);
            }
        }
    }

如果厚度是20或更小,我希望能够填充弧。同样,如果半径innerR是更大或更小,能够填充它。
目标是能够在任何情况下填充弧。

u3r8eeie

u3r8eeie1#

这里有一种绘制圆锥体的方法。
它看起来像雷达扫描,因此您可能需要定义扫描Angular 和旋转速度(根据计时器的间隔,当前旋转Angular 增加了多少)。
使用标准的System.Windows.Forms.Timer使包含图像的画布无效。

  • Radar* 轮廓(外部周长)在画布上居中,并根据指定的厚度绘制(因此它的大小始终与画布边界一致)。它不一定是正圆,也可以是椭圆(如图所示)
  • Cone* 部分是通过向GraphicsPath添加一个Arc来绘制的,并且是通过绘制两条线来闭合的,从外部GraphicsPath的中心点到Arc的起点和终点(我认为这是一个生成曲线圆锥图形的简单方法,它可以用于不同的情况,并且可以让您生成不同的形状,几乎不需要计算,请参阅有关此操作的代码)

它是用LinearGradientBrush填充的,靠近中心的部分比靠近边界的部分透明度低;按需调整
每次旋转Angular 达到360°时,都会重置为0
这将委托给计时器的Tick事件处理程序
=〉使用.Net 7构建,但如果您需要将其适配到.Net Framework,则只需更改using块的语法,从此处删除空值宽容运算符:canvas!.ClientRectangle和可空引用类型(例如,将object?更改为object

public partial class SomeForm : Form {
    public SomeForm() {
        InitializeComponent();
        radarTimer.Interval = 100;
        radarTimer.Tick += RadarTimer_Tick;
    }

    float coneSweepAngle = 36.0f;
    float coneRotationAngle = .0f;
    float radarSpeed = 1.8f;
    float radarThickness = 5.0f;
    System.Windows.Forms.Timer radarTimer = new System.Windows.Forms.Timer();

    private void RadarTimer_Tick(object? sender, EventArgs e) {
        coneRotationAngle += radarSpeed;
        coneRotationAngle %= 360.0f;
        canvas.Invalidate();
    }

    private void canvas_Paint(object sender, PaintEventArgs e) {
        var rect = canvas!.ClientRectangle;
        var center = new PointF(canvas.Width / 2.0f, canvas.Height / 2.0f);
        RectangleF outerRect = rect;
        outerRect.Inflate(-(radarThickness / 2.0f), -(radarThickness / 2.0f));

        e.Graphics.SmoothingMode = SmoothingMode.AntiAlias;

        using var pathOuter = new GraphicsPath();
        using var pathInner = new GraphicsPath();
        pathOuter.AddEllipse(outerRect);

        pathInner.StartFigure();
        pathInner.AddArc(outerRect, coneRotationAngle, coneSweepAngle);
        var arcPoints = pathInner.PathPoints;
        PointF first = arcPoints[0];
        PointF last = arcPoints[arcPoints.Length - 1];
        pathInner.AddLines(new[] { center, last, center, first });
        pathInner.CloseFigure();

        using var outerPen = new Pen(Color.FromArgb(100, Color.Red), radarThickness);
        using var innerBrush = new LinearGradientBrush(
            center, first, Color.FromArgb(200, Color.Orange), Color.FromArgb(20, Color.Orange));

        e.Graphics.FillPath(innerBrush, pathInner);
        e.Graphics.DrawPath(outerPen, pathOuter);
    }
}

它是这样工作的:

相关问题