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

CJM*_*CJM 8 .net c# gdi+ custom-controls winforms

我正在尝试使用具有圆角的用户控件.它没有固定的大小,但通常宽度不超过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));
    } 
Run Code Online (Sandbox Code Playgroud)

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

有没有更好的方法呢?

Rez*_*aei 11

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

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 = ClientRectangle;
    bounds.Width--; bounds.Height--;
    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();
}
Run Code Online (Sandbox Code Playgroud)

截图将是:

在此输入图像描述

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

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

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

下载

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


Gyö*_*zeg 2

Region仅当您想要“单击”透明区域时,设置才有意义。如果圆角不是那么大,而你只想让圆角在视觉上透明,你可以这样做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);
}
Run Code Online (Sandbox Code Playgroud)