Как я могу нарисовать прямоугольник со скругленными углами в качестве границы для округлой формы? - PullRequest
2 голосов
/ 10 июня 2019

Я создаю форму с закругленной границей (как показано на в этом вопросе ).
Поскольку у этого человека, похоже, тоже есть проблема, я не могу нарисовать округленную границу.

Это код, который я использовал для настройки фактической формы границы:

// ... within InitializeComponent ...
this.FormBorderStyle = FormBorderStyle.None;
IntPtr handle = CreateRoundRectRgn(0, 0, Width, Height, 20, 20);
Region = System.Drawing.Region.FromHrgn(handle);
DeleteObject(handle);

this.ResizeRedraw = true;

Это код, который переопределяет OnPaint и рисует контур границы.

protected override void OnPaint(PaintEventArgs e)
{
     // I've tried modifying the parameters here.
     GraphicsPath path = MyRoundedRectangle.Create(0, 0, Width, Height, 10, MyRoundedRectangle.RectangleCorners.All);

     Pen p = new Pen(Brushes.Black, 3f);
     e.Graphics.DrawPath(p, path);
}

Содержимое MyRoundedRectangle идентично коду, приведенному в этом вопросе , в котором ответ связан с этой страницей , в которой содержится код для MyRoundedRectangle.

Я бы хотел иметь полную окружающую границу, но вместо этого я получаю это: this

1 Ответ

4 голосов
/ 10 июня 2019

Базовая реализация того, что описано в комментариях.
Форма frmRoundCorners предоставляет некоторые свойства, которые позволяют рисовать округленную область с помощью пользовательского BackColor, пользовательского BorderColor и пользовательского внутреннего элемента.цвет границы, действующий как тень для внутренней стороны границы формы.

Сама форма реализована с использованием базового класса baseForm, полученного из Form, поэтому свойства формы можно задать в конструкторе форм.

Прозрачность активируется, устанавливая исходный BackColor формы равным TrasparencyKey, делая ее ClientArea полностью прозрачной, но рисуемой.
Исходная граница формы установлена ​​на FormBorderStyle.None в конструкторе базового класса.
Я не установил конкретный BackColor/TransparencyKey Цвет (его необходимо установить в конструкторе формы), потому что я думаю, что это то, с чем нужно экспериментировать.Я бы предложил средний серый цвет.Избегайте красных компонентов.

Форма может быть перемещена, нажав на любую точку ее ClientArea и перетащив ее.

Минимальная / максимальная кривизна формы и ее пользовательской границы установлена ​​на 15 и 180 градусов.Его нельзя изменить на другой диапазон с помощью PropertyGrid.
Округлые области формы и ее границы рисуются с помощью метода GraphicsPath.AddArc () , затем применяется матрица Matrix * 1038.* преобразование в объект Graphics в компонентах Scale и Transform (позиция).Компонент Размер не тронут.

Вот как это выглядит:

Rounded draggable borderless Form

using System.ComponentModel;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Windows.Forms;

[ToolboxItem(false)]
public partial class frmRoundCorners : baseForm
{
    private GraphicsPath pathRegion = new GraphicsPath(FillMode.Winding);
    private GraphicsPath pathBorder;
    Point pMousePosition = Point.Empty;

    public frmRoundCorners()
    {
        SetStyle(ControlStyles.AllPaintingInWmPaint |
                 ControlStyles.UserPaint |
                 ControlStyles.OptimizedDoubleBuffer |
                 ControlStyles.ResizeRedraw, true);
        InitializeComponent();
    }

    protected override void OnMouseDown(MouseEventArgs e)
    {
        if (e.Button == MouseButtons.Left) {
            pMousePosition = e.Location;
        }
        base.OnMouseDown(e);
    }

    protected override void OnMouseMove(MouseEventArgs e)
    {
        if (e.Button == MouseButtons.Left) {
            Point screenPos = PointToScreen(e.Location);
            this.Location = new Point(screenPos.X - pMousePosition.X, screenPos.Y - pMousePosition.Y);
        }
        base.OnMouseMove(e);
    }

    protected override void OnPaint(PaintEventArgs e)
    {
        base.OnPaint(e);

        e.Graphics.SmoothingMode = SmoothingMode.AntiAlias;
        e.Graphics.PixelOffsetMode = PixelOffsetMode.Half;
        RoundedCornerRectangle(this.ClientRectangle);
        RectangleF rect = pathRegion.GetBounds();
        float scaleX = 1 - (BorderSize / rect.Width);
        float scaleY = 1 - (BorderSize / rect.Height);
        using (Pen pen = new Pen(BorderColor, BorderSize))
        using (Pen penBorder = new Pen(InternalBorderColor, 2))
        using (Brush brush = new SolidBrush(FillColor))
        using (Matrix mx = new Matrix(scaleX, 0, 0, scaleY, (pen.Width / 2), (pen.Width / 2)))
        {
            e.Graphics.Transform = mx;
            e.Graphics.FillPath(brush, pathRegion);
            e.Graphics.DrawPath(penBorder, pathBorder);
            e.Graphics.DrawPath(pen, pathRegion);
        }
    }

    private void RoundedCornerRectangle(Rectangle r)
    {
        pathRegion = new GraphicsPath(FillMode.Alternate);
        float innerCurve = this.CurveAngle - this.m_PenSizeOffset;

        pathRegion.StartFigure();
        pathRegion.AddArc(r.X, r.Y, CurveAngle, CurveAngle, 180, 90);
        pathRegion.AddArc(r.Right - CurveAngle, r.Y, CurveAngle, CurveAngle, 270, 90);
        pathRegion.AddArc(r.Right - CurveAngle, r.Bottom - CurveAngle, CurveAngle, CurveAngle, 0, 90);
        pathRegion.AddArc(r.X, r.Bottom - CurveAngle, CurveAngle, CurveAngle, 90, 90);
        pathRegion.CloseFigure();

        pathBorder = new GraphicsPath();
        pathBorder.StartFigure();
        pathBorder.AddArc(r.X + m_PenSizeOffset, r.Y + m_PenSizeOffset, innerCurve, innerCurve, 180, 90);
        pathBorder.AddArc(r.Right - innerCurve - m_PenSizeOffset, r.Y + m_PenSizeOffset, innerCurve, innerCurve, 270, 90);
        pathBorder.AddArc(r.Right - innerCurve - m_PenSizeOffset, r.Bottom - innerCurve- m_PenSizeOffset, innerCurve, innerCurve, 0, 90);
        pathBorder.AddArc(r.X + m_PenSizeOffset, r.Bottom - innerCurve - m_PenSizeOffset, innerCurve, innerCurve, 90, 90);
        pathBorder.CloseFigure();
    }
}

public class baseForm : Form
{
    private Color m_InternalBorderColor = Color.FromArgb(128, 128, 128);
    private Color m_BorderColor = Color.Red;
    private Color m_FillColor = Color.WhiteSmoke;
    private float m_PenSize = 6f;
    private float m_CurveAngle = 60.0f;
    internal float m_PenSizeOffset = 3f;

    public baseForm() => InitializeComponent();
    private void InitializeComponent() => FormBorderStyle = FormBorderStyle.None;

    [EditorBrowsable(EditorBrowsableState.Always), Browsable(true), Category("Appearance")]
    [DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
    [DefaultValue(60.0f)]
    public virtual float CurveAngle
    {
        get => this.m_CurveAngle;
        set {
            this.m_CurveAngle = Math.Max(Math.Min(value, 180), 15);
            Invalidate();
        }
    }
    [EditorBrowsable(EditorBrowsableState.Always), Browsable(true), Category("Appearance")]
    [DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
    [DefaultValue(6.0f)]
    public virtual float BorderSize
    {
        get => this.m_PenSize;
        set {
            this.m_PenSize = value;
            this.m_PenSizeOffset = value / 2.0f;
            this.Invalidate();
        }
    }

    [EditorBrowsable(EditorBrowsableState.Always), Browsable(true), Category("Appearance")]
    [DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
    public virtual Color BorderColor
    {
        get => this.m_BorderColor;
        set {
            this.m_BorderColor = value;
            this.Invalidate();
        }
    }

    [EditorBrowsable(EditorBrowsableState.Always), Browsable(true), Category("Appearance")]
    [DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
    public virtual Color FillColor
    {
        get => this.m_FillColor;
        set {
            this.m_FillColor = value;
            this.Invalidate();
        }
    }

    [EditorBrowsable(EditorBrowsableState.Always), Browsable(true), Category("Appearance")]
    [DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
    [Description("Get or Set the Color of the internal border")]
    public virtual Color InternalBorderColor
    {
        get => this.m_InternalBorderColor;
        set {
            this.m_InternalBorderColor = value;
            this.Invalidate();
        }
    }

    [EditorBrowsable(EditorBrowsableState.Never), Browsable(false)]
    [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
    [DefaultValue(FormBorderStyle.None)]
    public new FormBorderStyle FormBorderStyle
    {
        get => base.FormBorderStyle;
        set => base.FormBorderStyle = FormBorderStyle.None;
    }
}
...