如何创建带圆角的用户控件?

我正在尝试使用具有圆角的用户控件。 它没有固定的大小,但通常宽度不超过120像素。

我需要用户控件及其内容(标签和表格)具有圆形边缘,看起来像一个圆形框。

我用过这段代码。

[DllImport("Gdi32.dll", EntryPoint = "CreateRoundRectRgn")] private static extern IntPtr CreateRoundRectRgn ( int nLeftRect, // x-coordinate of upper-left corner int nTopRect, // y-coordinate of upper-left corner int nRightRect, // x-coordinate of lower-right corner int nBottomRect, // y-coordinate of lower-right corner int nWidthEllipse, // height of ellipse int nHeightEllipse // width of ellipse ); public static System.Drawing.Region GetRoundedRegion(int controlWidth, int controlHeight) { return System.Drawing.Region.FromHrgn(CreateRoundRectRgn(0, 0, controlWidth - 5, controlHeight - 5, 20, 20)); } 

这给控件圆角但是在它运行了几次后我已经将多个用户控件添加到表单中它将导致泄漏,我将在我的用户控件上获得带有红叉的白盒。

有更好的方法吗?

如果你想要真正的圆角而且不仅仅是透明技巧,你可以使用这个例子:

 private int radius=20; [DefaultValue(20)] public int Radius { get { return radius; } set { radius = value; this.RecreateRegion(); } } private GraphicsPath GetRoundRectagle(Rectangle bounds, int radius) { GraphicsPath path = new GraphicsPath(); path.AddArc(bounds.X, bounds.Y, radius, radius, 180, 90); path.AddArc(bounds.X + bounds.Width - radius, bounds.Y, radius, radius, 270, 90); path.AddArc(bounds.X + bounds.Width - radius, bounds.Y + bounds.Height - radius, radius, radius, 0, 90); path.AddArc(bounds.X, bounds.Y + bounds.Height - radius, radius, radius, 90, 90); path.CloseAllFigures(); return path; } private void RecreateRegion() { var bounds = new Rectangle(this.ClientRectangle.Location, this.ClientRectangle.Size); bounds.Inflate(-1, -1); using (var path = GetRoundRectagle(bounds, this.Radius)) this.Region = new Region(path); this.Invalidate(); } protected override void OnSizeChanged(EventArgs e) { base.OnSizeChanged(e); this.RecreateRegion(); } 

截图将是:

在此处输入图像描述

这种方法与透明之间的区别:

  • 设置圆形区域,控件有圆角,你可以看到圆形部分背后的东西,尽管它是透明的,你会看到形状的背景。
  • 设置圆形区域,当您单击删除的圆角部分时,单击穿过该区域并到达后面,但如果使用透明技巧,则单击透明区域将由控件处理。

您可以使用这两个选项中的任何一个。 根据您的要求制作透明或设置区域。

下载

您可以在此处下载代码或克隆存储库:

  • R-aghaei / RoundCornerControlExample

只有当您想要“点击”透明区域时,才能设置区域。 如果圆角不是很大而你只想使角落在视觉上透明,你可以像Button那样做。

这个解决方案的优点是你可以在这里有一个很好的抗锯齿圆角,而一个区域的边缘总是很清晰。 没有提到Region实例持有非托管资源,应该以某种方式处理。

 protected override void OnPaint(PaintEventArgs e) { PaintTransparentBackground(this, e); // TODO: Paint your actual content here with rounded corners } private static void PaintTransparentBackground(Control c, PaintEventArgs e) { if (c.Parent == null || !Application.RenderWithVisualStyles) return; ButtonRenderer.DrawParentBackground(e.Graphics, c.ClientRectangle, c); } 

我已经回答了我自己的问题。

在Sinatr的评论之后,我发现我无法使用OnHandleCreated,因为我需要在我知道它的大小之前绘制对象。 在链接后,Sinatr提供了GetRoundedRegionexception

所以我所做的是在我的UserControl中添加一个IntPtr变量,该变量在CreateRoundRectRgn方法上使用句柄绘制。 在此触发之前,我使用DeleteObject删除旧句柄。

不是最佳解决方案,但现在似乎工作正常。

其他建议虽然好,但在我的情况下不会起作用。