c# - 使用 PathGradientBrush 创建的阴影显示出不需要的刺结果

标签 c# winforms gdi+ shadow graphicspath

我不明白为什么阴影路径在箭头帽附近有荆棘
引用我的截图。

using (GraphicsPath _Path = new GraphicsPath())
{
    Point[] _Points = new Point[] { 
            new Point { X = mouseDownX, Y = mouseDownY }, 
            new Point { X = lineEndX - 51, Y = mouseDownY },
            new Point { X = lineEndX - 51, Y = mouseDownY  - 20 },
            new Point { X = lineEndX, Y = mouseDownY + 5},
            new Point { X = lineEndX -51, Y = mouseDownY + 25},
            new Point { X = lineEndX -51, Y = mouseDownY +10 },
            new Point { X = mouseDownX, Y = mouseDownY +10 }};    
    _Path.AddPolygon(_Points);                                                                                     
    using (PathGradientBrush _Brush = new PathGradientBrush(_Path))
    {
        _Brush.WrapMode = WrapMode.Clamp;
        ColorBlend _ColorBlend = new ColorBlend(3);
        _ColorBlend.Colors = new Color[]{Color.Transparent, 
                                 Color.FromArgb(180, Color.DimGray),
                                 Color.FromArgb(180, Color.DimGray)};
        _ColorBlend.Positions = new float[] { 0f, 0.1f, 1f};
        _Brush.InterpolationColors = _ColorBlend;
        //myGraphics.Clip = new Region(_Path);
        myGraphics.FillPath(_Brush,_Path);
        //myGraphics.ResetClip();
    }
    Matrix _Matrix = new Matrix();
    int _ShadowDistance = -40;
    _Matrix.Translate(_ShadowDistance, _ShadowDistance);
    _Path.Transform(_Matrix);
    myGraphics.FillPath(Brushes.Red, _Path);
}

截图:
PathGradientBrush shadow

最佳答案

解决此问题的一种方法是指定内部 PathGradientBrushFocusScales ,在不影响颜色混合的情况下限制颜色衰减。

不幸的是,文档实际上并没有描述这个属性的用途。
您可以在这里阅读更好的描述:How to: Create a Path Gradient

可以在颜色位置上调整衰减。既然您指定了:

Positions = new float[] { 0.0f, 0.1f, 1.0f }

然后颜色衰减可以设置为:

brush.FocusScales = new PointF(0.1f, 1.0f);

水平比例可以调整,但不能超过总尺寸的一半,否则颜色混合将会受到影响:您将不会在形状边缘看到透明度抗锯齿。

设置 PixelOffsetMode 也可以获得更好的结果。到 PixelOffsetMode.Half
注意Docs中的描述是错误的,引用C++ documentation about this setting .

PathGradientBrush - FocusScales

示例实现。您可能只想在 MouseDown 事件上刷​​新绘图。
mousePosition 是鼠标指针的位置。可以在 MouseDown 事件处理程序中设置。

private Point mousePosition = Point.Empty;
private float lineSize = 100.0f;
private int shadowDistance = 16;

private void someControl_Paint(object sender, PaintEventArgs e)
{
    e.Graphics.SmoothingMode = SmoothingMode.AntiAlias;
    e.Graphics.PixelOffsetMode = PixelOffsetMode.Half;

    using (var path = new GraphicsPath(FillMode.Winding)) {
        PointF[] arrowPoints = new PointF[] {
            mousePosition,
            new PointF (mousePosition.X - 20f, mousePosition.Y + 10f),
            new PointF (mousePosition.X - 20f, mousePosition.Y + 3f),
            new PointF (mousePosition.X - lineSize, mousePosition.Y + 3f),
            new PointF (mousePosition.X - lineSize, mousePosition.Y - 3f),
            new PointF (mousePosition.X - 20f, mousePosition.Y - 3f),
            new PointF (mousePosition.X - 20f, mousePosition.Y - 10f)
        };
        path.AddLines(arrowPoints);

        using (var brush = new PathGradientBrush(path.PathPoints, WrapMode.Clamp)) {
            var blend = new ColorBlend() {
                Colors = new Color[] { Color.Transparent,
                                       Color.FromArgb(180, Color.DimGray),
                                       Color.FromArgb(180, Color.DimGray) },
                Positions = new float[] { 0.0f, 0.2f, 1.0f }
            };
            brush.FocusScales = new PointF(0.2f, 1.0f);
            brush.InterpolationColors = blend;
            e.Graphics.FillPath(brush, path);
        }
        using (var mx = new Matrix()) {
            mx.Translate(-shadowDistance, -shadowDistance);
            e.Graphics.Transform = mx;
            e.Graphics.FillPath(Brushes.Red, path);
        }
    }
}

关于c# - 使用 PathGradientBrush 创建的阴影显示出不需要的刺结果,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56217990/

相关文章:

c# - Visual Studio 2012 宏使用 VS2010 值

c# - 我可以在哪里放置静态字符串?

c# - 如何确定控件的可见性?

c# - C# App 中显示游戏图形的最佳方向

C++ GDI+ 对象内存泄漏/对象太多?

c# - 需要将函数包装在 c# 中的标准 try/catch 函数中

c# - 如何只解析字符串中的 float ?

c# - 将存储在对象中的 Enum 数据绑定(bind)到 Winforms ComboBox 中?

delphi - 在 Delphi 中创建 float 抗锯齿文本窗口

c# - SignalR:调用返回值的方法