[英]How to create a User Control with rounded corners?
我正在嘗試使用圓角的用戶控件。 它沒有固定的大小,但它的寬度通常不會超過 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();
}
屏幕截圖將是:
這種方法和透明化的區別:
您可以使用這兩個選項中的任何一個。 根據您的要求制作透明或設置區域。
下載
您可以在此處下載代碼或克隆存儲庫:
只有當您想“點擊”透明區域時,設置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);
}
我已經回答了我自己的問題。
根據 Sinatr 的評論,我發現我無法使用 OnHandleCreated,因為我需要在知道對象大小之前繪制對象。 按照鏈接 Sinatr 提供的GetRoundedRegion 異常
所以我所做的是向我的 UserControl 添加一個 IntPtr 變量,該變量在每次繪制時都分配在 CreateRoundRectRgn 方法上。 在此觸發之前,我正在使用 DeleteObject 刪除舊句柄。
不是最佳解決方案,但目前似乎工作正常。
其他建議雖然很好,但在我的情況下不起作用。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.