如何绘制圆角矩形作为圆角表格的边框? [英] How can I draw a rounded rectangle as the border for a rounded Form?

查看:96
本文介绍了如何绘制圆角矩形作为圆角表格的边框?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在创建一个具有圆形边框的表单(如方法,然后应用

 使用System.ComponentModel; 
使用System.Drawing;
使用System.Drawing.Drawing2D;
使用System.Windows.Forms;

[ToolboxItem(false)]
公共局部类frmRoundCorners:baseForm
{
private GraphicsPath pathRegion = new GraphicsPath(FillMode.Winding);
私人GraphicsPath pathBorder;
Point pMousePosition = Point.Empty;

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

受保护的覆盖无效OnMouseDown(MouseEventArgs e)
{
if(e.Button == MouseButtons.Left){
pMousePosition = e。位置;
}
base.OnMouseDown(e);
}

受保护的覆盖无效OnMouseMove(MouseEventArgs e)
{
if(e.Button == MouseButtons.Left){
Point screenPos = PointToScreen (e。位置);
this.Location = new Point(screenPos.X-pMousePosition.X,screenPos.Y-pMousePosition.Y);
}
base.OnMouseMove(e);
}

受保护的覆盖无效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);
使用(钢笔=​​新的Pen(BorderColor,BorderSize))
使用(钢笔PenBorder =新的Pen(InternalBorderColor,2))
使用(画笔=新的SolidBrush(FillColor))
使用(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();
}
}

公共类baseForm:表单
{
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;
私人浮点数m_CurveAngle = 60.0f;
内部浮点数m_PenSizeOffset = 3f;

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

[EditorBrowsable(EditorBrowsableState.Always),Browsable(true),Category(外观)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
[DefaultValue(60.0f) ]
公共虚拟浮点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)]
公共虚拟浮动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)]
公共虚拟颜色BorderColor
{
get => this.m_BorderColor;
set {
this.m_BorderColor = value;
this.Invalidate();
}
}

[EditorBrowsable(EditorBrowsableState.Always),Browsable(true),Category( Appearance)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
公共虚拟颜色FillColor
{
get => this.m_FillColor;
set {
this.m_FillColor = value;
this.Invalidate();
}
}

[EditorBrowsable(EditorBrowsableState.Always),Browsable(true),Category( Appearance)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
[Description(获取或设置内部边框的颜色)]
公共虚拟颜色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;
}
}


I'm creating a Form that has a rounded border (as shown in this question).
As this person also seems to have an issue with, I can't seem to draw a rounded border.

This is code I have used for setting up the actual border shape:

// ... 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;

This is code that overrides OnPaint and draws the border outline.

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);
}

The content of MyRoundedRectangle is identical to the code provided in this question, in which the answer linked to this page, which contains the code for MyRoundedRectangle.

I'd like to have a full surrounding border, but instead I get this:

解决方案

A base implementation of what is described in the comments.
The Form frmRoundCorners provides some properties that allow to draw its rounded area with a custom BackColor, a custom BorderColor and a custom inner border color, acting as a shadow for the internal side of the Form's border.

The Form itself is implemented using a base class, baseForm, derived from Form, so the Form's properties can be set in the Form designer.

The transparency is activated setting the Form's original BackColor equal to its TrasparencyKey, making its ClientArea completely transparent, but drawable.
The Form's original border is set to FormBorderStyle.None in the base class constructor.
I didn't set a specific BackColor/TransparencyKey Color (it must be set in the Form's designer) because I think it's something one need to experiment with. I'ld suggest a medium gray color. Avoid red components.

The Form can be moved, clicking on any point of its ClientArea and dragging it.

The minimum/maximum curvature of the Form and its custom Border is set to 15 and 180 degrees. It cannot be changed to a different range using the PropertyGrid.
The rounded area ot the Form and its border are drawn using the GraphicsPath.AddArc() method, then applying a Matrix transformation to the Graphics object, both in the Scale and the Transform (position) components. The Size component is untouched.

This is what it looks like:

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;
    }
}

这篇关于如何绘制圆角矩形作为圆角表格的边框?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆