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

标签 c# .net winforms custom-controls gdi+

我想拥有一个圆角的用户控件。它没有固定大小,但通常宽度不会超过 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();
    }
}

[System.Runtime.InteropServices.DllImport("gdi32.dll")]
private static extern IntPtr CreateRoundRectRgn(int nLeftRect, int nTopRect,
    int nRightRect, int nBottomRect, int nWidthEllipse, int nHeightEllipse);

private GraphicsPath GetRoundRectagle(Rectangle bounds, int radius)
{
    float r = radius;
    GraphicsPath path = new GraphicsPath();
    path.StartFigure();
    path.AddArc(bounds.Left, bounds.Top, r, r, 180, 90);
    path.AddArc(bounds.Right - r, bounds.Top, r, r, 270, 90);
    path.AddArc(bounds.Right - r, bounds.Bottom - r, r, r, 0, 90);
    path.AddArc(bounds.Left, bounds.Bottom - r, r, r, 90, 90);
    path.CloseFigure();
    return path;
}

private void RecreateRegion()
{
    var bounds = ClientRectangle;

    //using (var path = GetRoundRectagle(bounds, this.Radius))
    //    this.Region = new Region(path);

    //Better round rectangle
    this.Region = Region.FromHrgn(CreateRoundRectRgn(bounds.Left, bounds.Top,
        bounds.Right, bounds.Bottom, Radius, radius));
    this.Invalidate();
}

protected override void OnSizeChanged(EventArgs e)
{
    base.OnSizeChanged(e);
    this.RecreateRegion();
}

带有 GraphicsPath 的区域:

enter image description here

带有 Windows API 的区域:

enter image description here

这种方式和透明化的区别:

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

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

下载

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

关于c# - 如何创建带圆角的用户控件?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32987649/

相关文章:

c# - 如何将大型 SQL 脚本解析成批处理?

c# - 如何检查 (c#) ControlCollection.Find() 是否返回结果

c# - 如何在没有外部工具的情况下在 C#/VS2010 中自定义自动插入的 XML 注释

c# - Directory.CreateDirectory 是异步的还是什么?

c# - 如何将信息从 OnAuthenticated 事件传递到 Controller 和登录?

c# - 为什么使用只有静态方法的类?

c# - 无法访问 Azure 上发布的 Web api

c# - C++ 中的 DirectX11 引擎和 C# 中的接口(interface)

winforms - 使用报表设计器创建或编辑报表 (.rdlc) 时 Visual Studio 2010 崩溃

c# - 为什么 WindowsPrincipal.IsInRole 总是为 "Administrators"组返回 false?