我目前正在尝试覆写正在建置之自订控件的OnPaint()
方法。
这个对象只是一个简单的Panel,但我试图让它看起来像一个不同的类型,就像这样:
x1c 0d1x。
我正在使用GraphicsPath来帮助我尝试并完成此任务,但它的外观/行为与我预期的工作方式不符,它当前的外观如下:
的数据。
下面是我一直在重新创建图1的代码:
private GraphicsPath GetFigurePath(RectangleF rect)
{
GraphicsPath path = new GraphicsPath();
Point TopLeft = new Point((int)rect.X, (int)rect.Y);
Point TopRight = new Point((int)rect.X + (int)rect.Width, (int)rect.Height);
Point BottomLeft = new Point((int)rect.X, (int)rect.Y + (int)rect.Height);
Point BottomRight = new Point((int)rect.X + (int)rect.Width, (int)rect.Y + (int)rect.Height);
Point MidPoint = new Point((TopLeft.X + BottomLeft.X) / 2, (TopLeft.Y + BottomLeft.Y) / 2);
Point Fulcrum = new Point((int)MidPoint.X + (int)rect.Width, MidPoint.Y);
path.StartFigure();
// The rectangle
path.AddLine(TopLeft, TopRight);
path.AddLine(TopRight, BottomRight);
path.AddLine(BottomRight, BottomLeft);
path.AddLine(BottomLeft, TopLeft);
// The pointy end
path.AddLine(TopRight, Fulcrum);
path.AddLine(Fulcrum, BottomRight);
path.CloseFigure();
return path;
}
protected override void OnPaint(PaintEventArgs e)
{
if (HasBorderStyle) {
base.OnPaint(e);
this.FlatStyle = FlatStyle.Flat;
this.Size = new Size(DEFAULT_WIDTH, DEFAULT_HEIGHT);
this.BackColor = Color.Silver;
this.ForeColor = Color.White;
e.Graphics.SmoothingMode = SmoothingMode.AntiAlias;
RectangleF rectSurface = new RectangleF(0, 0, this.DEFAULT_WIDTH, this.DEFAULT_HEIGHT);
RectangleF rectBorder = new RectangleF(1, 1, this.DEFAULT_WIDTH - 0.8f, this.DEFAULT_HEIGHT - 1);
using (GraphicsPath pathSurface = GetFigurePath(rectSurface))
using (GraphicsPath pathBorder = GetFigurePath(rectBorder))
using (Pen penSurface = new Pen(this.Parent.BackColor, 2))
using (Pen penBorder = new Pen(borderColour, borderSize)) {
penBorder.Alignment = PenAlignment.Inset;
this.Region = new Region(pathSurface);
e.Graphics.DrawPath(penSurface, pathSurface);
e.Graphics.DrawPath(penBorder, pathBorder);
}
}
}
谁能告诉我我错过了什么或者我做错了什么?
1条答案
按热度按时间wmomyfyw1#
使用Regions定义表示非矩形形状的自定义控件的可见区域的一些指针和示例。
float
)。总是产生正确的计算。例如:Rotate Point around pivot Point repeatedly,以查看差异。
DEFAULT_WIDTH
和DEFAULT_HEIGHT
。由于控件的大小可以随时调整,无论是在设计阶段还是在执行阶段,因此使用固定的量值并没有实际的用处(假设这就是这些值所代表的意义)。在任何情况下,您都需要使用控件的目前工作区做为主要指涉:该值由Control.ClientRectangle属性返回。OnPaint()
覆盖中设置的,而是在OnResize()
或OnLayout()
覆盖中设置的,这取决于您正在生成的控件的功能。设置属性,如您在那里拥有的
FlatStyle = FlatStyle.Flat;
(您是否从Label派生控件?),也不属于绘图过程:您可能会生成级联事件,导致控件不断地自我重画(直到崩溃)。当你设置一个控件的区域时,要修改它的形状,你需要考虑到区域不支持抗锯齿,因此你不能沿着它创建的边框绘制。你需要 * 缩小 * 绘图区域,这样你总是在你定义的区域内绘制。或者,您可以创建一个完全透明/半透明的控件并绘制所需的任何内容(形状和/或位图)。但这是一个不同的问题,让我们坚持区域和创建它的GraphicsPath。
在范例程式码中,
GetRegionPath()
方法会产生GraphicsPath对象,该对象是透过定义形体的PointF
坐标建立,然后使用AddLines()方法建立形体。此处显示的自定义控件使用SetStyle()在其构造函数中进行设置:
这将启用双缓冲,并使控件在调整大小时重画。
然后在
OnResize()
覆盖中重置区域。在
OnPaint()
中,会根据目前的工作区,再次呼叫GetRegionPath()
方法以取得GraphicsPath对象。然后使用简单的Matrix缩放GraphicsPath:
(see Flip the GraphicsPath that draws the text/string中Matrix功能的说明)
这将根据Border的大小缩放GraphicsPath(大于
1.0f
的值将放大,小于1.0f
的值将缩小)。然后,它会以边界的测量值向右和向下移动(平移)。
如果未设置Border,则不会缩放或 * 移动 * GraphicsPath:例如:
这允许在Region内绘制形状及其边框(如果有)。
在这种情况下,可以应用消除锯齿,并且形状的边框看起来 * 平滑 *。
这是在设计阶段的外观:
在运行时:
另请参阅:
How to avoid visual artifacts of colored border of zoomable UserControl with rounded corners?
How can I draw a rounded rectangle as the border for a rounded Form?
A shadow created with PathGradientBrush shows undesired thorn results显示器
自定义控件: