我有一个Form
,其中包含:
TrackBar
(最小值= 1,最大值= 200,表示缩放百分比);UserControl
的BorderStyle = BorderStyle.None
。trackBar1.Value = 100;
BackColor = Color.Gray;
private void trackBar1_Scroll(object sender, EventArgs e)
{
userControl11.SetZoomFactor(trackBar1.Value / 100F);
}
internal float MyBaseWidth;
public UserControl1()
{
InitializeComponent();
MyBaseWidth = Width;
SetZoomFactor(1);
}
protected override void OnPaint(PaintEventArgs e)
{
base.OnPaint(e);
e.Graphics.SmoothingMode = SmoothingMode.HighQuality;
e.Graphics.CompositingQuality = CompositingQuality.HighQuality;
e.Graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
Pen p = new Pen(Color.Yellow);
e.Graphics.DrawPath(p, GraphicsPathWithBorder);
}
internal GraphicsPath GraphicsPathWithBorder;
internal void SetZoomFactor(float z)
{
Width = (int)(MyBaseWidth * z);
GraphicsPathWithBorder = RoundedCornerRectangle(ClientRectangle);
Region = new Region(GraphicsPathWithBorder);
}
internal static GraphicsPath RoundedCornerRectangle(Rectangle r)
{
GraphicsPath path = new GraphicsPath();
float size = 10 * 2F;
path.StartFigure();
path.AddArc(r.X, r.Y,
size, size, 180, 90);
path.AddArc((r.X + (r.Width - size)), r.Y,
size, size, 270, 90);
path.AddArc((r.X + (r.Width - size)), (r.Y + (r.Height - size)),
size, size, 0, 90);
path.AddArc(r.X, (r.Y + (r.Height - size)),
size, size, 90, 90);
path.CloseFigure();
return path;
}
缩小后,黄色边框的右侧变为不可见,当放大时,右侧有多个黄色边框。
更新:
答案是可行的,但是有一部分控制超出了边界。 curveSize = 20
右上角的屏幕截图:
并为curveSize = 24
:
我建议使用稍微不同的方法来绘制边框和用户控件的内容,这也应该可以修复重绘控件时生成的工件。
为控件创建区域然后按原样绘制区域时,绘画的外边框不会消除锯齿:别名像素落在区域之外。当边界被绘制在区域的边界周围时,当然会产生相同的效果。
在这里,我应用了一个Scale Matrix和一个Translate Matrix,它在外部Region的内部缩放和移动Region的边界,定义了控件的边界。 缩放的大小和平移变换由笔大小决定。 关于Matrix用法的更多信息:Flip the GraphicsPath
在这种情况下,当边框被绘制时,边框的外部抗锯齿部分位于区域边界内,并且保留了抗锯齿。
Control的背景颜色设置为Color.Transparent
(用户控件自身支持颜色透明度)。
我还添加了一些(非装饰的)属性,允许定义内部颜色(Control的BackgroundColor)和边框的大小和颜色。其余的或多或少都是以前的样子。
样品结果:
using System.Drawing;
using System.Drawing.Drawing2D;
public partial class RoundControl : UserControl
{
private GraphicsPath GraphicsPathWithBorder;
private float MyBaseWidth;
private float m_PenSize = 2f;
private Color m_BorderColor = Color.Yellow;
private Color m_FillColor = Color.Green;
public RoundControl()
{
this.ResizeRedraw = true;
InitializeComponent();
MyBaseWidth = Width;
}
public float BorderSize
{
get => this.m_PenSize;
set {
this.m_PenSize = value;
this.Invalidate();
}
}
public Color BorderColor
{
get => this.m_BorderColor;
set {
this.m_BorderColor = value;
this.Invalidate();
}
}
public Color FillColor
{
get => this.m_FillColor;
set {
this.m_FillColor = value;
this.Invalidate();
}
}
protected override void OnLayout(LayoutEventArgs e) {
this.UpdateRegion();
base.OnLayout(e);
}
protected override void OnPaint(PaintEventArgs e)
{
base.OnPaint(e);
e.Graphics.SmoothingMode = SmoothingMode.AntiAlias;
RectangleF rect = GraphicsPathWithBorder.GetBounds();
float scaleX = 1 - ((m_PenSize + 1) / rect.Width);
float scaleY = 1 - ((m_PenSize + 1) / rect.Height);
using (Pen pen = new Pen(m_BorderColor, m_PenSize))
using (Brush brush = new SolidBrush(m_FillColor))
using (Matrix mx = new Matrix(scaleX, 0, 0, scaleY, pen.Width / 2, pen.Width / 2))
{
e.Graphics.Transform = mx;
e.Graphics.FillPath(brush, GraphicsPathWithBorder);
e.Graphics.DrawPath(pen, GraphicsPathWithBorder);
}
}
private void UpdateRegion() {
GraphicsPathWithBorder = RoundedCornerRectangle(ClientRectangle);
Region = new Region(GraphicsPathWithBorder);
this.Invalidate();
}
internal void SetZoomFactor(float z) {
int newWidth = (int)(MyBaseWidth * z);
if (newWidth <= (30 + this.m_PenSize * 2)) return;
this.Width = newWidth;
this.UpdateRegion();
}
private GraphicsPath RoundedCornerRectangle(Rectangle r)
{
GraphicsPath path = new GraphicsPath();
float curveSize = 10 * 2.4F;
path.StartFigure();
path.AddArc(r.X, r.Y, curveSize, curveSize, 180, 90);
path.AddArc(r.Right - curveSize, r.Y, curveSize, curveSize, 270, 90);
path.AddArc(r.Right - curveSize, r.Bottom - curveSize, curveSize, curveSize, 0, 90);
path.AddArc(r.X, r.Bottom - curveSize, curveSize, curveSize, 90, 90);
path.CloseFigure();
return path;
}
}