Winform控件優(yōu)化Paint事件實(shí)現(xiàn)圓角組件及提取繪制圓角的方法
前言
Windows 11下所有控件已經(jīng)默認(rèn)采用圓角,其效果更好、相對(duì)有著更好的優(yōu)化,只是這是默認(rèn)的行為,無(wú)法進(jìn)一步自定義。
注意兩點(diǎn):
- Paint事件方法中實(shí)現(xiàn)圓角控件不要通過(guò)事件參數(shù)
e.ClipRectangle
獲取控件區(qū)域范圍 - 注意設(shè)置控件背景透明(雖然Winform中的透明不是完全透明,
實(shí)現(xiàn)圓角控件比較好的一個(gè)思路是在控件的Paint事件中進(jìn)行繪制,不太好的地方在于每次實(shí)現(xiàn)時(shí)都要添加事件處理,且不能在設(shè)計(jì)器中實(shí)時(shí)看到效果。
只要有Paint事件的組件都實(shí)現(xiàn)繪制圓角【如果沒(méi)有,也可以通過(guò)將控件放在Panel中,借助Panel的圓角實(shí)現(xiàn)】。
Paint事件中實(shí)現(xiàn)圓角控件
注意:由于控件在Paint事件方法中進(jìn)行了重新繪制,因此文本也被覆蓋了,需要處理文本的繪制顯示
新建項(xiàng)目 CustomControlRound
,窗體中添加兩個(gè)Panel、三個(gè)Button、一個(gè)Label控件。button設(shè)置Flat樣式、邊框?yàn)?。
然后在Paint事件方法中調(diào)用繪制圓角區(qū)域的方法(具體代碼參見(jiàn)下一部分的擴(kuò)展方法),具體如下:
public partial class Form1 : Form { public Form1() { InitializeComponent(); panel1.Paint += Panel1_Paint; panel2.Paint += Panel2_Paint; panel1.BackColor = panel2.BackColor = Color.Transparent; button1.Paint += Button1_Paint; button1.FlatStyle = FlatStyle.Flat; button1.FlatAppearance.BorderSize = 0; button1.FlatAppearance.MouseDownBackColor = Color.Transparent; button1.FlatAppearance.MouseOverBackColor = Color.Transparent; button1.FlatAppearance.CheckedBackColor = Color.Transparent; button2.Paint += Button1_Paint; button2.FlatStyle = FlatStyle.Flat; button2.FlatAppearance.BorderSize = 0; //button2.FlatAppearance.BorderColor = SystemColors.ButtonFace; button2.FlatAppearance.MouseDownBackColor = Color.Transparent; button2.FlatAppearance.MouseOverBackColor = Color.Transparent; button2.FlatAppearance.CheckedBackColor = Color.Transparent; button3.Paint += Button1_Paint; button3.FlatStyle = FlatStyle.Flat; button3.FlatAppearance.BorderSize = 0; //button3.FlatAppearance.BorderColor = SystemColors.ButtonFace; button3.FlatAppearance.MouseDownBackColor = Color.Transparent; button3.FlatAppearance.MouseOverBackColor = Color.Transparent; button3.FlatAppearance.CheckedBackColor = Color.Transparent; label1.Paint += Label1_Paint; label1.BackColor = Color.Transparent; } private void Label1_Paint(object sender, PaintEventArgs e) { var l = (Label)sender; // e.Graphics.DrawRoundRectAndCusp(e.ClipRectangle, 18, Color.FromArgb(180, 200, 210), Color.FromArgb(120, 120, 100)); // 不推薦 e.Graphics.DrawRoundRectAndCusp(new Rectangle(0,0, l.Width,l.Height), 18, Color.FromArgb(180, 200, 210), Color.FromArgb(120, 120, 100)); } private void Button1_Paint(object sender, PaintEventArgs e) { var btn = (Button)sender; e.Graphics.DrawRoundRectAndCusp(new Rectangle(0, 0, btn.Width, btn.Height), 18, Color.FromArgb(0, 122, 204), Color.FromArgb(8, 39, 57)); ((Button)sender).NotifyDefault(false); // 去除窗體失去焦點(diǎn)時(shí)最新激活的按鈕邊框外觀樣式 } private void Panel1_Paint(object sender, PaintEventArgs e) { var panel = sender as Panel; var rect=e.Graphics.DrawRoundRectAndCusp(new Rectangle(0, 0, panel.Width, panel.Height), 18, Color.FromArgb(90, 143, 0), Color.FromArgb(41, 67, 0),true, rectAlign); } private void Panel2_Paint(object sender, PaintEventArgs e) { var panel = sender as Panel; var rect = e.Graphics.DrawRoundRectAndCusp(new Rectangle(0, 0, panel.Width, panel.Height), 18, Color.FromArgb(113, 113, 113), Color.FromArgb(0, 0, 0)); } }
查看效果:
在Paint事件中不需要調(diào)用
base.OnPaint(e);
,只有在繼承控件重寫(xiě)OnPaint
方法時(shí),才應(yīng)該(在函數(shù)方法開(kāi)始時(shí))調(diào)用base.OnPaint(e);
。
提取繪制圓角矩形和旁邊小尖角的代碼為擴(kuò)展方法
介紹
下面是提取的擴(kuò)展方法,對(duì)源代碼進(jìn)行了修改和優(yōu)化。
- 1、可繪制漸變背景色、指定背景色、指定畫(huà)刷繪制的背景;可指定漸變背景的方向
- 2、指定圓角半徑的繪制,如果半徑小于等于0,將繪制直角矩形。
- 3、指定三角小尖,默認(rèn)不繪制;指定三角小尖的位置,可供八個(gè)位置選擇
- 4、三角小尖的大小,目前感覺(jué)作為參數(shù)傳遞不夠靈活,如果需要調(diào)整可直接從代碼中修改,主要修改部分為:
// 尖角的大小 默認(rèn)為 開(kāi)始位置為_(kāi)radius 底邊為20,高度為13的等腰三角形 var cuspHemlineStart = _radius; var cuspHemlineLength = 20; var cuspHeight = 13;
擴(kuò)展方法
擴(kuò)展方法代碼如下,將其放在namespace System.Drawing.Drawing2D
下,可直接方便的從Graphics對(duì)象調(diào)用。
/// <summary> /// 繪制可漸變的圓角矩形,并指定是否有三角小尖及其位置 /// </summary> /// <param name="g"></param> /// <param name="rectangle">矩形區(qū)域</param> /// <param name="_radius">圓角半徑</param> /// <param name="begin_bgcolor">背景漸變開(kāi)始色</param> /// <param name="end_bgcolor">背景漸變結(jié)束色</param> /// <param name="cusp">是否有三角小尖,默認(rèn)無(wú)</param> /// <param name="rectAlign">三角小尖的位置,默認(rèn)右上</param> /// <param name="gradientMode">漸變模式,默認(rèn)垂直方向漸變</param> public static void DrawRoundRectAndCusp(this Graphics g, Rectangle rectangle, int _radius, Color begin_bgcolor, Color end_bgcolor, bool cusp = false, RectangleAlign rectAlign= RectangleAlign.RightTop, LinearGradientMode gradientMode = LinearGradientMode.Vertical) { ////抗鋸齒 等模式在Graphics外層自定義設(shè)置 //g.SmoothingMode = SmoothingMode.AntiAlias; //漸變填充 LinearGradientBrush linearGradientBrush = new LinearGradientBrush(rectangle, begin_bgcolor, end_bgcolor, gradientMode); g.DrawRoundRectAndCusp(rectangle, _radius, linearGradientBrush, cusp, rectAlign); } /// <summary> /// 繪制指定背景的圓角矩形,并指定是否有三角小尖及其位置 /// </summary> /// <param name="g"></param> /// <param name="rectangle">矩形區(qū)域</param> /// <param name="_radius">圓角半徑</param> /// <param name="bgcolor">指定背景色</param> /// <param name="cusp">是否有三角小尖,默認(rèn)無(wú)</param> /// <param name="rectAlign">三角小尖的位置,默認(rèn)右上</param> public static void DrawRoundRectAndCusp(this Graphics g, Rectangle rectangle, int _radius, Color bgcolor, bool cusp = false, RectangleAlign rectAlign = RectangleAlign.RightTop) { ////抗鋸齒 等模式在Graphics外層自定義設(shè)置 //g.SmoothingMode = SmoothingMode.AntiAlias; //漸變填充 var brush = new SolidBrush(bgcolor); g.DrawRoundRectAndCusp(rectangle, _radius, brush, cusp, rectAlign); } /// <summary> /// 繪制Brush畫(huà)刷的圓角矩形,并指定是否有三角小尖及其位置 /// </summary> /// <param name="g"></param> /// <param name="rectangle">矩形區(qū)域</param> /// <param name="_radius">圓角半徑</param> /// <param name="bgbrush">指定背景畫(huà)刷</param> /// <param name="cusp">是否有三角小尖,默認(rèn)無(wú)</param> /// <param name="rectAlign">三角小尖的位置,默認(rèn)右上</param> public static void DrawRoundRectAndCusp(this Graphics g, Rectangle rectangle, int _radius, Brush bgbrush, bool cusp = false, RectangleAlign rectAlign = RectangleAlign.RightTop) { ////抗鋸齒 盡可能高質(zhì)量繪制 g.TextRenderingHint = System.Drawing.Text.TextRenderingHint.AntiAlias; g.PixelOffsetMode = PixelOffsetMode.HighQuality; g.SmoothingMode = SmoothingMode.AntiAlias; // SmoothingMode.HighQuality g.CompositingQuality = CompositingQuality.HighQuality; g.InterpolationMode = InterpolationMode.HighQualityBilinear; var rect = rectangle; //畫(huà)尖角 對(duì)應(yīng)的變更rect區(qū)域 if (cusp) { // 尖角的大小 默認(rèn)為 開(kāi)始位置為_(kāi)radius 底邊為20,高度為13的等腰三角形 var cuspHemlineStart = _radius; var cuspHemlineLength = 20; var cuspHeight = 13; // 讓位出來(lái)的間隔暫時(shí)為尖角高度-1 var span = cuspHeight - 1; // 三角頂點(diǎn) PointF p1, p2, p3; switch (rectAlign) { case RectangleAlign.AboveLeft: p1 = new PointF(rectangle.X + cuspHemlineStart, rectangle.Y + cuspHeight); p2 = new PointF(rectangle.X + cuspHemlineStart + cuspHemlineLength, rectangle.Y + cuspHeight); p3 = new PointF(rectangle.X + cuspHemlineStart + cuspHemlineLength / 2, rectangle.Y); rect = new Rectangle(rectangle.X, rectangle.Y + span, rectangle.Width, rectangle.Height - span); break; case RectangleAlign.AboveRight: p1 = new PointF(rectangle.Right - cuspHemlineStart, rectangle.Y + cuspHeight); p2 = new PointF(rectangle.Right - cuspHemlineStart - cuspHemlineLength, rectangle.Y + cuspHeight); p3 = new PointF(rectangle.Right - cuspHemlineStart - cuspHemlineLength / 2, rectangle.Y); rect = new Rectangle(rectangle.X, rectangle.Y + span, rectangle.Width, rectangle.Height - span); break; case RectangleAlign.RightBottom: p1 = new PointF(rectangle.Right - cuspHeight, rectangle.Bottom - cuspHemlineStart); p2 = new PointF(rectangle.Right - cuspHeight, rectangle.Bottom - cuspHemlineStart - cuspHemlineLength); p3 = new PointF(rectangle.Right, rectangle.Bottom - cuspHemlineStart - cuspHemlineLength / 2); rect = new Rectangle(rectangle.X, rectangle.Y, rectangle.Width - span, rectangle.Height); break; case RectangleAlign.BelowRight: p1 = new PointF(rectangle.Right - cuspHemlineStart, rectangle.Bottom - cuspHeight); p2 = new PointF(rectangle.Right - cuspHemlineStart - cuspHemlineLength, rectangle.Bottom - cuspHeight); p3 = new PointF(rectangle.Right - cuspHemlineStart - cuspHemlineLength / 2, rectangle.Bottom); rect = new Rectangle(rectangle.X, rectangle.Y, rectangle.Width, rectangle.Height - span); break; case RectangleAlign.BelowLeft: p1 = new PointF(rectangle.X + cuspHemlineStart, rectangle.Bottom - cuspHeight); p2 = new PointF(rectangle.X + cuspHemlineStart + cuspHemlineLength, rectangle.Bottom - cuspHeight); p3 = new PointF(rectangle.X + cuspHemlineStart + cuspHemlineLength / 2, rectangle.Bottom); rect = new Rectangle(rectangle.X, rectangle.Y, rectangle.Width, rectangle.Height - span); break; case RectangleAlign.LeftBottom: p1 = new PointF(rectangle.X + cuspHeight, rectangle.Bottom - cuspHemlineStart); p2 = new PointF(rectangle.X + cuspHeight, rectangle.Bottom - cuspHemlineStart - cuspHemlineLength); p3 = new PointF(rectangle.X, rectangle.Bottom - cuspHemlineStart - cuspHemlineLength / 2); rect = new Rectangle(rectangle.X + span, rectangle.Y, rectangle.Width - span, rectangle.Height); break; case RectangleAlign.LeftTop: p1 = new PointF(rectangle.X + cuspHeight, rectangle.Y + cuspHemlineStart); p2 = new PointF(rectangle.X + cuspHeight, rectangle.Y + cuspHemlineStart + cuspHemlineLength); p3 = new PointF(rectangle.X, rectangle.Y + cuspHemlineStart + cuspHemlineLength / 2); rect = new Rectangle(rectangle.X + span, rectangle.Y, rectangle.Width - span, rectangle.Height); break; case RectangleAlign.RightTop: default: p1 = new PointF(rectangle.Right - cuspHeight, rectangle.Y + cuspHemlineStart); p2 = new PointF(rectangle.Right - cuspHeight, rectangle.Y + cuspHemlineStart + cuspHemlineLength); p3 = new PointF(rectangle.Right, rectangle.Y + cuspHemlineStart + cuspHemlineLength / 2); rect = new Rectangle(rectangle.X, rectangle.Y, rectangle.Width - span, rectangle.Height); break; } PointF[] ptsArray = new PointF[] { p1, p2, p3 }; // 填充參數(shù)點(diǎn)所指定的多邊形內(nèi)部 g.FillPolygon(bgbrush, ptsArray); } //填充 g.FillPath(bgbrush, rect.GetRoundedRectPath(_radius)); } /// <summary> /// 根據(jù)普通矩形得到圓角矩形的路徑 【根據(jù)矩形區(qū)域rect,計(jì)算呈現(xiàn)radius圓角的Graphics路徑】 /// </summary> /// <param name="rect">原始矩形</param> /// <param name="radius">半徑</param> /// <returns>圖形路徑</returns> public static GraphicsPath GetRoundedRectPath(this Rectangle rect, int radius) { #region 正確繪制圓角矩形區(qū)域 int R = radius*2; Rectangle arcRect = new Rectangle(rect.Location, new Size(R, R)); GraphicsPath path = new GraphicsPath(); if (radius <= 0) { path.AddRectangle(rect); } else { // 左上圓弧 左手坐標(biāo)系,順時(shí)針為正 從180開(kāi)始,轉(zhuǎn)90度 path.AddArc(arcRect, 180, 90); // 右上圓弧 arcRect.X = rect.Right - R; path.AddArc(arcRect, 270, 90); // 右下圓弧 arcRect.Y = rect.Bottom - R; path.AddArc(arcRect, 0, 90); // 左下圓弧 arcRect.X = rect.Left; path.AddArc(arcRect, 90, 90); } //path.CloseFigure(); // 閉合路徑中所有開(kāi)放圖形,并形成新圖形 path.CloseAllFigures(); return path; #endregion } /// <summary> /// 獲取圓角矩形的路徑 /// </summary> /// <param name="rect">原始矩形</param> /// <param name="radius">半徑</param> /// <returns>圖形路徑</returns> public static GraphicsPath GetRoundedRectPath(int x, int y, int width, int height, int radius) { Rectangle rect = new Rectangle(x, y, width, height); return rect.GetRoundedRectPath(radius); }
測(cè)試尖角的顯示位置
復(fù)制幾個(gè)Panel,在Paint事件中分別處理尖角的位置
panel1.Paint += Panel1_Paint; panel3.Paint += Panel1_Paint; panel4.Paint += Panel1_Paint; panel5.Paint += Panel1_Paint; panel6.Paint += Panel1_Paint; panel7.Paint += Panel1_Paint; panel8.Paint += Panel1_Paint; panel9.Paint += Panel1_Paint; /// ...... private void Panel1_Paint(object sender, PaintEventArgs e) { var panel = sender as Panel; var rectAlign = RectangleAlign.RightTop; switch (panel.Name) { case "panel3": rectAlign = RectangleAlign.AboveLeft; break; case "panel4": rectAlign = RectangleAlign.AboveRight; break; case "panel5": rectAlign = RectangleAlign.BelowLeft; break; case "panel6": rectAlign = RectangleAlign.BelowRight; break; case "panel7": rectAlign = RectangleAlign.LeftBottom; break; case "panel8": rectAlign = RectangleAlign.LeftTop; break; case "panel9": rectAlign = RectangleAlign.RightBottom; break; default: break; } var rect=e.Graphics.DrawRoundRectAndCusp(new Rectangle(0, 0, panel.Width, panel.Height), 18, Color.FromArgb(90, 143, 0), Color.FromArgb(41, 67, 0),true, rectAlign); e.Graphics.DrawText(rect, "這是一個(gè)Panel控件,非常適合顯示消息", Color.White, panel.Font); }
查看效果:
重繪控件后文本的處理
由于重新繪制導(dǎo)致文本也被覆蓋的情況,有比較常見(jiàn)的兩種處理方法:
- 重繪控件的同時(shí),重繪文本文字
- 通過(guò)添加Label控件實(shí)現(xiàn)文本處理
同時(shí)重繪文本
同樣將繪制文本的方法提取為擴(kuò)展方法,借助StringFormat
字符串格式對(duì)象實(shí)現(xiàn)文字的布局處理。
不推薦使用
Graphics.DrawString
繪制按鈕控件(Rectangle區(qū)域)內(nèi)的文字,當(dāng)然DrawString也有一定有時(shí)比如文字方向的處理。
/// <summary> /// 繪制(控件區(qū)域)文本內(nèi)容 /// </summary> /// <param name="g"></param> /// <param name="rect"></param> /// <param name="text"></param> /// <param name="color"></param> /// <param name="font"></param> /// <param name="_textAlign">文字布局,默認(rèn)居中。實(shí)際測(cè)試并未真正的居中,垂直方向偏上,改為通過(guò)計(jì)算rect的中心位置實(shí)現(xiàn),使用微軟雅黑還好點(diǎn),字體大小最好偶數(shù)</param> /// <param name="rtl">是否RightToLeft 無(wú)效果,不推薦使用</param> public static void DrawText(this Graphics g, Rectangle rect, string text, Color color, Font font, ContentAlignment _textAlign = ContentAlignment.MiddleCenter, bool rtl=false) { var formatFlags = TextFormatFlags.HorizontalCenter | TextFormatFlags.VerticalCenter; // 默認(rèn)居中 switch (_textAlign) { case ContentAlignment.TopLeft: formatFlags = TextFormatFlags.Top | TextFormatFlags.Left; break; case ContentAlignment.TopCenter: formatFlags = TextFormatFlags.Top | TextFormatFlags.HorizontalCenter; break; case ContentAlignment.TopRight: formatFlags = TextFormatFlags.Top | TextFormatFlags.Right; break; case ContentAlignment.MiddleLeft: formatFlags = TextFormatFlags.VerticalCenter | TextFormatFlags.Left; break; case ContentAlignment.MiddleRight: formatFlags = TextFormatFlags.VerticalCenter | TextFormatFlags.Right; break; case ContentAlignment.BottomLeft: formatFlags = TextFormatFlags.Bottom | TextFormatFlags.Left; break; case ContentAlignment.BottomCenter: formatFlags = TextFormatFlags.Bottom | TextFormatFlags.HorizontalCenter; break; case ContentAlignment.BottomRight: formatFlags = TextFormatFlags.Bottom | TextFormatFlags.Right; break; case ContentAlignment.MiddleCenter: default: break; } if (rtl) { formatFlags |= TextFormatFlags.RightToLeft; // 無(wú)效果 } TextRenderer.DrawText(g, text, font, rect, color, formatFlags); }
要注意添加了小三角后的文字繪制區(qū)域問(wèn)題,如果使用默認(rèn)的全部預(yù)期有可能導(dǎo)致文字超出范圍,且,布局也不是相對(duì)于繪制的主體。如下圖對(duì)比的效果。
因此,可修改圓角繪制的函數(shù),使其返回繪制后的主體區(qū)域。
private void Panel1_Paint(object sender, PaintEventArgs e) { var panel = sender as Panel; var rect=e.Graphics.DrawRoundRectAndCusp(new Rectangle(0, 0, panel.Width, panel.Height), 18, Color.FromArgb(90, 143, 0), Color.FromArgb(41, 67, 0),true, rectAlign); //e.Graphics.DrawText(e.ClipRectangle, "這是一個(gè)Panel控件,非常適合顯示消息", Color.White, panel.Font); // 使用合適的區(qū)域 e.Graphics.DrawText(rect, "這是一個(gè)Panel控件,非常適合顯示消息", Color.White, panel.Font); }
通過(guò)添加Label控件實(shí)現(xiàn)對(duì)文本的處理【有尖角時(shí)需要額外處理】
label2.Text = "我是Label顯示在圓角按鈕上"; label2.Parent = button1; label2.AutoSize = false; label2.Dock = DockStyle.Fill; label2.BackColor = Color.Transparent; label2.TextAlign = ContentAlignment.MiddleCenter; label2.ForeColor = Color.Wheat;
Paint事件中繪制圓角的優(yōu)點(diǎn)
完全由用戶繪制按鈕區(qū)域?qū)崿F(xiàn)圓角【之前文章介紹過(guò)】,可以發(fā)現(xiàn),與直接在Paint事件中實(shí)現(xiàn)圓角,有著一定的鋸齒,雖然不是很嚴(yán)重,但是還是Paint事件中實(shí)現(xiàn)的圓角看著相對(duì)好一些。
之前完全由用戶繪制控件區(qū)域出現(xiàn)鋸齒的問(wèn)題,原因在于使用
new Region(graphicPath)
構(gòu)造函數(shù)創(chuàng)建的新Region對(duì)象,創(chuàng)建的Region無(wú)法實(shí)現(xiàn)抗鋸齒,即使開(kāi)始抗鋸齒和高質(zhì)量繪制(無(wú)法應(yīng)用到最終的Region)。[唯一的]解決辦法,是不創(chuàng)建新的Region,直接繪制無(wú)鋸齒圖形【無(wú)法對(duì)Region進(jìn)行抗鋸齒】。
窗體失去焦點(diǎn)時(shí)按鈕外觀邊框問(wèn)題
窗體失去焦點(diǎn)后,Button會(huì)顯示出一個(gè)邊框(即使已經(jīng)設(shè)置BorderSize為0),只有在窗體失去焦點(diǎn)后,最后一個(gè)被激活過(guò)的Button(點(diǎn)擊過(guò)的)才會(huì)出現(xiàn)。
比較好的解決辦法是在Button的Paint事件中執(zhí)行Button.NotifyDefault(false)
方法。
下面是幾種解決方式:
- 通過(guò)繼承Button控件,重寫(xiě)NotifyDefault方法實(shí)現(xiàn)。
class MyButton:Button { public override void NotifyDefault(bool value) { base.NotifyDefault(false); } }
- 設(shè)置FlatAppearance.BorderColor顏色與下層背景色一致
或者,還有一個(gè)取巧的解決辦法,就是,設(shè)置FlatAppearance.BorderColor
為Button按鈕后面的背景色,這樣就看不出來(lái),類似沒(méi)有的效果。如 button1.FlatAppearance.BorderColor = SystemColors.Control;
。
- 在Button的Paint事件方法中調(diào)用
NotifyDefault(false)
或者,不是繼承重寫(xiě)B(tài)utton控件,直接在Button的Paint事件中,調(diào)用Button.NotifyDefault(false);
方法。
private void Button1_Paint(object sender, PaintEventArgs e) { var btn = (Button)sender; e.Graphics.DrawRoundRectAndCusp(new Rectangle(0, 0, btn.Width, btn.Height), 18, Color.FromArgb(0, 122, 204), Color.FromArgb(8, 39, 57)); ((Button)sender).NotifyDefault(false); // 去除窗體失去焦點(diǎn)時(shí)最新激活的按鈕邊框外觀樣式 }
Paint事件中繪制控件的問(wèn)題【不要使用(事件)參數(shù)e.ClipRectangle】
直接看下圖演示,在發(fā)生控件大小、位置調(diào)整等需要重繪時(shí),會(huì)發(fā)生控件錯(cuò)亂、顯示不完整重疊等問(wèn)題。
比如Panel事件中,原本的寫(xiě)法為:
var rect=e.Graphics.DrawRoundRectAndCusp(e.ClipRectangle, 18, Color.FromArgb(90, 143, 0), Color.FromArgb(41, 67, 0),true, rectAlign);
將其改為轉(zhuǎn)換傳遞過(guò)來(lái)的控件參數(shù)為Panel對(duì)象,并通過(guò)其寬高獲取其繪制區(qū)域:
var rect=e.Graphics.DrawRoundRectAndCusp(new Rectangle(0, 0, panel.Width, panel.Height), 18, Color.FromArgb(90, 143, 0), Color.FromArgb(41, 67, 0),true, rectAlign);
修改后錯(cuò)亂問(wèn)題就不存在了:
到此這篇關(guān)于Winform控件優(yōu)化Paint事件實(shí)現(xiàn)圓角組件及提取繪制圓角的擴(kuò)展方法的文章就介紹到這了,更多相關(guān)Winform控件優(yōu)化內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
C#使用Socket實(shí)現(xiàn)發(fā)送和接收?qǐng)D片的方法
這篇文章主要介紹了C#使用Socket實(shí)現(xiàn)發(fā)送和接收?qǐng)D片的方法,涉及C#操作socket發(fā)送與接收文件的使用技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下2015-04-04如何用C#在PC上查找連接藍(lán)牙設(shè)備并實(shí)現(xiàn)數(shù)據(jù)傳輸
這篇文章主要介紹了如何用C#在PC上查找連接藍(lán)牙設(shè)備并實(shí)現(xiàn)數(shù)據(jù)傳輸,幫助大家更好的理解和學(xué)習(xí)使用c#,感興趣的朋友可以了解下2021-03-03WPF調(diào)用ffmpeg實(shí)現(xiàn)屏幕錄制
這篇文章主要為大家詳細(xì)介紹了WPF如何調(diào)用ffmpeg實(shí)現(xiàn)屏幕錄制,文中的示例代碼講解詳細(xì),對(duì)我們學(xué)習(xí)或工作有一定幫助,感興趣的小伙伴可以了解一下2023-05-05C#使用表達(dá)式樹(shù)(LambdaExpression)動(dòng)態(tài)更新類的屬性值(示例代碼)
這篇文章主要介紹了C#使用表達(dá)式樹(shù)(LambdaExpression)動(dòng)態(tài)更新類的屬性值,本文通過(guò)示例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2022-01-01