Winform控件優(yōu)化Paint事件實現(xiàn)圓角組件及提取繪制圓角的方法_第1頁
Winform控件優(yōu)化Paint事件實現(xiàn)圓角組件及提取繪制圓角的方法_第2頁
Winform控件優(yōu)化Paint事件實現(xiàn)圓角組件及提取繪制圓角的方法_第3頁
Winform控件優(yōu)化Paint事件實現(xiàn)圓角組件及提取繪制圓角的方法_第4頁
Winform控件優(yōu)化Paint事件實現(xiàn)圓角組件及提取繪制圓角的方法_第5頁
已閱讀5頁,還剩13頁未讀, 繼續(xù)免費閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認領(lǐng)

文檔簡介

第Winform控件優(yōu)化Paint事件實現(xiàn)圓角組件及提取繪制圓角的方法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;

privatevoidLabel1_Paint(objectsender,PaintEventArgse)

varl=(Label)sender;

//e.Graphics.DrawRoundRectAndCusp(e.ClipRectangle,18,Color.FromArgb(180,200,210),Color.FromArgb(120,120,100));//不推薦

e.Graphics.DrawRoundRectAndCusp(newRectangle(0,0,l.Width,l.Height),18,Color.FromArgb(180,200,210),Color.FromArgb(120,120,100));

privatevoidButton1_Paint(objectsender,PaintEventArgse)

varbtn=(Button)sender;

e.Graphics.DrawRoundRectAndCusp(newRectangle(0,0,btn.Width,btn.Height),18,Color.FromArgb(0,122,204),Color.FromArgb(8,39,57));

((Button)sender).NotifyDefault(false);//去除窗體失去焦點時最新激活的按鈕邊框外觀樣式

privatevoidPanel1_Paint(objectsender,PaintEventArgse)

varpanel=senderasPanel;

varrect=e.Graphics.DrawRoundRectAndCusp(newRectangle(0,0,panel.Width,panel.Height),18,Color.FromArgb(90,143,0),Color.FromArgb(41,67,0),true,rectAlign);

privatevoidPanel2_Paint(objectsender,PaintEventArgse)

varpanel=senderasPanel;

varrect=e.Graphics.DrawRoundRectAndCusp(newRectangle(0,0,panel.Width,panel.Height),18,Color.FromArgb(113,113,113),Color.FromArgb(0,0,0));

}

查看效果:

在Paint事件中不需要調(diào)用base.OnPaint(e);,只有在繼承控件重寫OnPaint方法時,才應(yīng)該(在函數(shù)方法開始時)調(diào)用base.OnPaint(e);。

提取繪制圓角矩形和旁邊小尖角的代碼為擴展方法

介紹

下面是提取的擴展方法,對源代碼進行了修改和優(yōu)化。

1、可繪制漸變背景色、指定背景色、指定畫刷繪制的背景;可指定漸變背景的方向2、指定圓角半徑的繪制,如果半徑小于等于0,將繪制直角矩形。3、指定三角小尖,默認不繪制;指定三角小尖的位置,可供八個位置選擇4、三角小尖的大小,目前感覺作為參數(shù)傳遞不夠靈活,如果需要調(diào)整可直接從代碼中修改,主要修改部分為:

//尖角的大小默認為開始位置為_radius底邊為20,高度為13的等腰三角形

varcuspHemlineStart=_radius;

varcuspHemlineLength=20;

varcuspHeight=13;

擴展方法

擴展方法代碼如下,將其放在namespaceSystem.Drawing.Drawing2D下,可直接方便的從Graphics對象調(diào)用。

///summary

///繪制可漸變的圓角矩形,并指定是否有三角小尖及其位置

////summary

///paramname="g"/param

///paramname="rectangle"矩形區(qū)域/param

///paramname="_radius"圓角半徑/param

///paramname="begin_bgcolor"背景漸變開始色/param

///paramname="end_bgcolor"背景漸變結(jié)束色/param

///paramname="cusp"是否有三角小尖,默認無/param

///paramname="rectAlign"三角小尖的位置,默認右上/param

///paramname="gradientMode"漸變模式,默認垂直方向漸變/param

publicstaticvoidDrawRoundRectAndCusp(thisGraphicsg,Rectanglerectangle,int_radius,Colorbegin_bgcolor,Colorend_bgcolor,boolcusp=false,RectangleAlignrectAlign=RectangleAlign.RightTop,LinearGradientModegradientMode=LinearGradientMode.Vertical)

////抗鋸齒等模式在Graphics外層自定義設(shè)置

//g.SmoothingMode=SmoothingMode.AntiAlias;

//漸變填充

LinearGradientBrushlinearGradientBrush=newLinearGradientBrush(rectangle,begin_bgcolor,end_bgcolor,gradientMode);

g.DrawRoundRectAndCusp(rectangle,_radius,linearGradientBrush,cusp,rectAlign);

///summary

///繪制指定背景的圓角矩形,并指定是否有三角小尖及其位置

////summary

///paramname="g"/param

///paramname="rectangle"矩形區(qū)域/param

///paramname="_radius"圓角半徑/param

///paramname="bgcolor"指定背景色/param

///paramname="cusp"是否有三角小尖,默認無/param

///paramname="rectAlign"三角小尖的位置,默認右上/param

publicstaticvoidDrawRoundRectAndCusp(thisGraphicsg,Rectanglerectangle,int_radius,Colorbgcolor,boolcusp=false,RectangleAlignrectAlign=RectangleAlign.RightTop)

////抗鋸齒等模式在Graphics外層自定義設(shè)置

//g.SmoothingMode=SmoothingMode.AntiAlias;

//漸變填充

varbrush=newSolidBrush(bgcolor);

g.DrawRoundRectAndCusp(rectangle,_radius,brush,cusp,rectAlign);

///summary

///繪制Brush畫刷的圓角矩形,并指定是否有三角小尖及其位置

////summary

///paramname="g"/param

///paramname="rectangle"矩形區(qū)域/param

///paramname="_radius"圓角半徑/param

///paramname="bgbrush"指定背景畫刷/param

///paramname="cusp"是否有三角小尖,默認無/param

///paramname="rectAlign"三角小尖的位置,默認右上/param

publicstaticvoidDrawRoundRectAndCusp(thisGraphicsg,Rectanglerectangle,int_radius,Brushbgbrush,boolcusp=false,RectangleAlignrectAlign=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;

varrect=rectangle;

//畫尖角對應(yīng)的變更rect區(qū)域

if(cusp)

//尖角的大小默認為開始位置為_radius底邊為20,高度為13的等腰三角形

varcuspHemlineStart=_radius;

varcuspHemlineLength=20;

varcuspHeight=13;

//讓位出來的間隔暫時為尖角高度-1

varspan=cuspHeight-1;

//三角頂點

PointFp1,p2,p3;

switch(rectAlign)

caseRectangleAlign.AboveLeft:

p1=newPointF(rectangle.X+cuspHemlineStart,rectangle.Y+cuspHeight);

p2=newPointF(rectangle.X+cuspHemlineStart+cuspHemlineLength,rectangle.Y+cuspHeight);

p3=newPointF(rectangle.X+cuspHemlineStart+cuspHemlineLength/2,rectangle.Y);

rect=newRectangle(rectangle.X,rectangle.Y+span,rectangle.Width,rectangle.Height-span);

break;

caseRectangleAlign.AboveRight:

p1=newPointF(rectangle.Right-cuspHemlineStart,rectangle.Y+cuspHeight);

p2=newPointF(rectangle.Right-cuspHemlineStart-cuspHemlineLength,rectangle.Y+cuspHeight);

p3=newPointF(rectangle.Right-cuspHemlineStart-cuspHemlineLength/2,rectangle.Y);

rect=newRectangle(rectangle.X,rectangle.Y+span,rectangle.Width,rectangle.Height-span);

break;

caseRectangleAlign.RightBottom:

p1=newPointF(rectangle.Right-cuspHeight,rectangle.Bottom-cuspHemlineStart);

p2=newPointF(rectangle.Right-cuspHeight,rectangle.Bottom-cuspHemlineStart-cuspHemlineLength);

p3=newPointF(rectangle.Right,rectangle.Bottom-cuspHemlineStart-cuspHemlineLength/2);

rect=newRectangle(rectangle.X,rectangle.Y,rectangle.Width-span,rectangle.Height);

break;

caseRectangleAlign.BelowRight:

p1=newPointF(rectangle.Right-cuspHemlineStart,rectangle.Bottom-cuspHeight);

p2=newPointF(rectangle.Right-cuspHemlineStart-cuspHemlineLength,rectangle.Bottom-cuspHeight);

p3=newPointF(rectangle.Right-cuspHemlineStart-cuspHemlineLength/2,rectangle.Bottom);

rect=newRectangle(rectangle.X,rectangle.Y,rectangle.Width,rectangle.Height-span);

break;

caseRectangleAlign.BelowLeft:

p1=newPointF(rectangle.X+cuspHemlineStart,rectangle.Bottom-cuspHeight);

p2=newPointF(rectangle.X+cuspHemlineStart+cuspHemlineLength,rectangle.Bottom-cuspHeight);

p3=newPointF(rectangle.X+cuspHemlineStart+cuspHemlineLength/2,rectangle.Bottom);

rect=newRectangle(rectangle.X,rectangle.Y,rectangle.Width,rectangle.Height-span);

break;

caseRectangleAlign.LeftBottom:

p1=newPointF(rectangle.X+cuspHeight,rectangle.Bottom-cuspHemlineStart);

p2=newPointF(rectangle.X+cuspHeight,rectangle.Bottom-cuspHemlineStart-cuspHemlineLength);

p3=newPointF(rectangle.X,rectangle.Bottom-cuspHemlineStart-cuspHemlineLength/2);

rect=newRectangle(rectangle.X+span,rectangle.Y,rectangle.Width-span,rectangle.Height);

break;

caseRectangleAlign.LeftTop:

p1=newPointF(rectangle.X+cuspHeight,rectangle.Y+cuspHemlineStart);

p2=newPointF(rectangle.X+cuspHeight,rectangle.Y+cuspHemlineStart+cuspHemlineLength);

p3=newPointF(rectangle.X,rectangle.Y+cuspHemlineStart+cuspHemlineLength/2);

rect=newRectangle(rectangle.X+span,rectangle.Y,rectangle.Width-span,rectangle.Height);

break;

caseRectangleAlign.RightTop:

default:

p1=newPointF(rectangle.Right-cuspHeight,rectangle.Y+cuspHemlineStart);

p2=newPointF(rectangle.Right-cuspHeight,rectangle.Y+cuspHemlineStart+cuspHemlineLength);

p3=newPointF(rectangle.Right,rectangle.Y+cuspHemlineStart+cuspHemlineLength/2);

rect=newRectangle(rectangle.X,rectangle.Y,rectangle.Width-span,rectangle.Height);

break;

PointF[]ptsArray=newPointF[]{p1,p2,p3};

//填充參數(shù)點所指定的多邊形內(nèi)部

g.FillPolygon(bgbrush,ptsArray);

//填充

g.FillPath(bgbrush,rect.GetRoundedRectPath(_radius));

///summary

///根據(jù)普通矩形得到圓角矩形的路徑【根據(jù)矩形區(qū)域rect,計算呈現(xiàn)radius圓角的Graphics路徑】

////summary

///paramname="rect"原始矩形/param

///paramname="radius"半徑/param

///returns圖形路徑/returns

publicstaticGraphicsPathGetRoundedRectPath(thisRectanglerect,intradius)

#region正確繪制圓角矩形區(qū)域

intR=radius*2;

RectanglearcRect=newRectangle(rect.Location,newSize(R,R));

GraphicsPathpath=newGraphicsPath();

if(radius=0)

path.AddRectangle(rect);

else

//左上圓弧左手坐標系,順時針為正從180開始,轉(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();

//閉合路徑中所有開放圖形,并形成新圖形

path.CloseAllFigures();

returnpath;

#endregion

///summary

///獲取圓角矩形的路徑

////summary

///paramname="rect"原始矩形/param

///paramname="radius"半徑/param

///returns圖形路徑/returns

publicstaticGraphicsPathGetRoundedRectPath(intx,inty,intwidth,intheight,intradius)

Rectanglerect=newRectangle(x,y,width,height);

returnrect.GetRoundedRectPath(radius);

}

測試尖角的顯示位置

復(fù)制幾個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;

///......

privatevoidPanel1_Paint(objectsender,PaintEventArgse)

varpanel=senderasPanel;

varrectAlign=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;

varrect=e.Graphics.DrawRoundRectAndCusp(newRectangle(0,0,panel.Width,panel.Height),18,Color.FromArgb(90,143,0),Color.FromArgb(41,67,0),true,rectAlign);

e.Graphics.DrawText(rect,"這是一個Panel控件,非常適合顯示消息",Color.White,panel.Font);

}

查看效果:

重繪控件后文本的處理

由于重新繪制導(dǎo)致文本也被覆蓋的情況,有比較常見的兩種處理方法:

重繪控件的同時,重繪文本文字通過添加Label控件實現(xiàn)文本處理

同時重繪文本

同樣將繪制文本的方法提取為擴展方法,借助StringFormat字符串格式對象實現(xiàn)文字的布局處理。

不推薦使用Graphics.DrawString繪制按鈕控件(Rectangle區(qū)域)內(nèi)的文字,當然DrawString也有一定有時比如文字方向的處理。

///summary

///繪制(控件區(qū)域)文本內(nèi)容

////summary

///paramname="g"/param

///paramname="rect"/param

///paramname="text"/param

///paramname="color"/param

///paramname="font"/param

///paramname="_textAlign"文字布局,默認居中。實際測試并未真正的居中,垂直方向偏上,改為通過計算rect的中心位置實現(xiàn),使用微軟雅黑還好點,字體大小最好偶數(shù)/param

///paramname="rtl"是否RightToLeft無效果,不推薦使用/param

publicstaticvoidDrawText(thisGraphicsg,Rectanglerect,stringtext,Colorcolor,Fontfont,ContentAlignment_textAlign=ContentAlignment.MiddleCenter,boolrtl=false)

varformatFlags=TextFormatFlags.HorizontalCenter|TextFormatFlags.VerticalCenter;//默認居中

switch(_textAlign)

caseContentAlignment.TopLeft:

formatFlags=TextFormatFlags.Top|TextFormatFlags.Left;

break;

caseContentAlignment.TopCenter:

formatFlags=TextFormatFlags.Top|TextFormatFlags.HorizontalCenter;

break;

caseContentAlignment.TopRight:

formatFlags=TextFormatFlags.Top|TextFormatFlags.Right;

break;

caseContentAlignment.MiddleLeft:

formatFlags=TextFormatFlags.VerticalCenter|TextFormatFlags.Left;

break;

caseContentAlignment.MiddleRight:

formatFlags=TextFormatFlags.VerticalCenter|TextFormatFlags.Right;

break;

caseContentAlignment.BottomLeft:

formatFlags=TextFormatFlags.Bottom|TextFormatFlags.Left;

break;

caseContentAlignment.BottomCenter:

formatFlags=TextFormatFlags.Bottom|TextFormatFlags.HorizontalCenter;

break;

caseContentAlignment.BottomRight:

formatFlags=TextFormatFlags.Bottom|TextFormatFlags.Right;

break;

caseContentAlignment.MiddleCenter:

default:

break;

if(rtl)

formatFlags|=TextFormatFlags.RightToLeft;//無效果

TextRenderer.DrawText(g,text,font,rect,color,formatFlags);

}

要注意添加了小三角后的文字繪制區(qū)域問題,如果使用默認的全部預(yù)期有可能導(dǎo)致文字超出范圍,且,布局也不是相對于繪制的主體。如下圖對比的效果。

因此,可修改圓角繪制的函數(shù),使其返回繪制后的主體區(qū)域。

privatevoidPanel1_Paint(objectsender,PaintEventArgse)

varpanel=senderasPanel;

varrect=e.Graphics.DrawRoundRectAndCusp(newRectangle(0,0,panel.Width,panel.Height),18,Color.FromArgb(90,143,0),Color.FromArgb(41,67,0),true,rectAlign);

//e.Graphics.DrawText(e.ClipRectangle,"這是一個Panel控件,非常適合顯示消息",Color.White,panel.Font);

//使用合適的區(qū)域

e.Graphics.DrawText(rect,"這是一個Panel控件,非常適合顯示消息",Color.White,panel.Font);

}

通過添加Label控件實現(xiàn)對文本的處理【有尖角時需要額外處理】

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)點

完全由用戶繪制按鈕區(qū)域?qū)崿F(xiàn)圓角【之前文章介紹過】,可以發(fā)現(xiàn),與直接在Paint事件中實現(xiàn)圓角,有著一定的鋸齒,雖然不是很嚴重,但是還是Paint事件中實現(xiàn)的圓角看著相對好一些。

之前完全由用戶繪制

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論