如何重画Windows控件
例1:改变控件属性
使用Visual Studio .NET来开发软件时,可以利用其强大的IDE环境来手工设定界面控件的属性。但是如果你要使你整个程序上的控件风格都是某种特定属性的话,那最好的方法就是自己重载控件类。
让我们从最简单的System.Windows.Forms.Button类开始尝试,按钮有如下的常用属性:
BackColor--按钮的背景颜色
Cursor--鼠标状态
Enabled--是否启用按钮
FlatStyle--按钮的扁平风格
Font--按钮上的字体
ForeColor--按钮的前景颜色
Height--按钮的高度
Image--按钮上的图片
Location--按钮上的位置
Text--按钮上的文字
Visible--按钮是否可见
Width--按钮的宽度
在下面的这个例子里面,我们得到一个蓝底白字的扁平按钮:
1、在Visual C# .NET中新建一个Windows Application项目,命名为OwnDrawButton1;
2、往项目中添加一个MyButton类,将其改为继承System.Windows.Forms.Button,并在构造函数中添加修改属性的代码;
就像这样:
public class MyButton : System.Windows.Forms.Button { public MyButton() { //set the back color to blue BackColor = System.Drawing.Color.Blue; //set the appearance style to flat FlatStyle = System.Windows.Forms.FlatStyle.Flat; //use system default font Font = System.Windows.Forms.Control.DefaultFont; //use white color to write text and draw the border ForeColor = System.Drawing.Color.White; } }
3、拖一个按钮到Form1上,右击鼠标,单击"View Code",在代码中用"MyButton"替换掉"System.Windows.Forms.Button";
4、编译执行。
现在,你就能在你的界面上看到自定义的控件了(如图1)。
图1 通过代码修改控件属性的按钮
例2:重画简单控件
仅通过改变控件的属性值来自定义控件,在很多情况下是不能令人满意的。例如如果想把Windows XP里那种风格的按钮放到Windows 98/2000下,你就得自己来画那些按钮了。
在这种情况下,你可以通过重载OnPaint()等事件来重画按钮。你也可以通过EventHandler来让控件响应更多的事件,例如,我们可以给按钮添加鼠标悬停效果,给MouseEnter和MouseLeave分别加上EeventHandler,这样,你在事件响应函数里写的代码就会被调用。
下面是一个例子,这个例子编写了一个类似Windows XP中按钮风格的控件:
1、在Visual C# .NET中新建一个Windows Application项目,命名为OwnDrawButton2;
2、往项目中添加一个MyButton类,将其改为继承System.Windows.Forms.Button,在构造函数中添加修改属性的代码和事件响应关联代码,并编写各函数代码,如下所列:
using System; using System.Drawing; using System.Windows; using System.Windows.Forms; namespace OwnDrawButton2 { public class MyButton : System.Windows.Forms.Button { //state variable for mouse down private bool mouseDown=false; //state variable for mouse hover private bool mouseHover=false; public MyButton() { //set the control UserPaint SetStyle(ControlStyles.UserPaint,true); //EventHandler for MouseDown MouseDown+=new MouseEventHandler(OnMouseDown); //EventHandler for MouseUp MouseUp+=new MouseEventHandler(OnMouseUp); //EventHandler for MouseEnter MouseEnter+=new EventHandler(OnMouseEnter); //EventHandler for MouseLeave MouseLeave+=new EventHandler(OnMouseLeave); Height=23;//Default Height Width=75;//Default Width } protected override void OnPaint(PaintEventArgs pe) { //first, paint the control with parent form's background color pe.Graphics.FillRectangle(new SolidBrush(Parent.BackColor), pe.ClipRectangle); //if the button is disabled, draw the disable style if (Enabled == false) { DrawDisableButton(pe.Graphics); } else if (mouseDown) { //when mouse down, draw the mouse down style DrawMouseDownButton(pe.Graphics); } else if (mouseHover) { //when mouse hover, draw the mouse hover style DrawMouseHoverButton(pe.Graphics); } else if (Focused) { //when mouse is focused but not mouse hover, //draw the focus style DrawContainFocusButton(pe.Graphics); } else//else, draw the normal style { DrawNormalButton(pe.Graphics); } WriteText(pe.Graphics);//write text } private void OnMouseDown(object sender,MouseEventArgs e) { mouseDown=true; //mouse is down now } private void OnMouseUp(object sender,MouseEventArgs e) { mouseDown=false; //mouse is up now //call paint action PaintEventArgs pe = new PaintEventArgs(CreateGraphics(),ClientRectangle); OnPaint(pe); } private void OnMouseEnter(object sender,EventArgs e) { mouseHover=true; //mouse hover on //call paint action PaintEventArgs pe = new PaintEventArgs(CreateGraphics(),ClientRectangle); OnPaint(pe); } private void OnMouseLeave(object sender,EventArgs e) { mouseHover=false; //mouse is not hover on //call paint action PaintEventArgs pe = new PaintEventArgs(CreateGraphics(),ClientRectangle); OnPaint(pe); } private void DrawBorder(Graphics g,int state) { if (state==1)//draw normal style broder { Pen p = new Pen(SystemColors.ControlLightLight,2); g.DrawLine(p,1,1,1,Height-2); g.DrawLine(p,1,1,Width-2,1); g.DrawLine(p,Width-1,2,Width-1,Height-2); g.DrawLine(p,2,Height-1,Width-2,Height-1); } else if (state==2)//draw hover style border { Pen p = new Pen(Color.Yellow,2); g.DrawLine(p,1,1,1,Height-2); g.DrawLine(p,1,1,Width-2,1); g.DrawLine(p,Width-1,2,Width-1,Height-2); g.DrawLine(p,2,Height-1,Width-2,Height-1); } else if (state==3)//draw pressed style border { Pen p = new Pen(SystemColors.ControlDark,2); g.DrawLine(p,1,1,1,Height-2); g.DrawLine(p,1,1,Width-2,1); g.DrawLine(p,Width-1,2,Width-1,Height-2); g.DrawLine(p,2,Height-1,Width-2,Height-1); } else if (state==4)//draw disabled style border { Pen p = new Pen(SystemColors.ControlLight,2); g.DrawLine(p,1,1,1,Height-2); g.DrawLine(p,1,1,Width-2,1); g.DrawLine(p,Width-1,2,Width-1,Height-2); g.DrawLine(p,2,Height-1,Width-2,Height-1); } else if (state==5)//draw default style border { Pen p = new Pen(Color.SkyBlue,2); g.DrawLine(p,1,1,1,Height-2); g.DrawLine(p,1,1,Width-2,1); g.DrawLine(p,Width-1,2,Width-1,Height-2); g.DrawLine(p,2,Height-1,Width-2,Height-1); } if (state==4)//draw disable style border { Pen p = new Pen(Color.FromArgb(161,161,146),1); g.DrawLine(p,0,2,0,Height-3); g.DrawLine(p,2,0,Width-3,0); g.DrawLine(p,Width-1,2,Width-1,Height-3); g.DrawLine(p,2,Height-1,Width-3,Height-1); g.DrawLine(p,0,2,2,0); g.DrawLine(p,0,Height-3,2,Height-1); g.DrawLine(p,Width-3,0,Width-1,2); g.DrawLine(p,Width-3,Height-1,Width-1,Height-3); } else//draw normal style border { g.DrawLine(Pens.Black,0,2,0,Height-3); g.DrawLine(Pens.Black,2,0,Width-3,0); g.DrawLine(Pens.Black,Width-1,2,Width-1,Height-3); g.DrawLine(Pens.Black,2,Height-1,Width-3,Height-1); g.DrawLine(Pens.Black,0,2,2,0); g.DrawLine(Pens.Black,0,Height-3,2,Height-1); g.DrawLine(Pens.Black,Width-3,0,Width-1,2); g.DrawLine(Pens.Black,Width-3,Height-1, Width-1,Height-3); } } private void DrawNormalButton(Graphics g)//draw normal style button { //draw normal style border DrawBorder(g,1); //paint background PaintBack(g,SystemColors.ControlLightLight); } private void DrawMouseHoverButton(Graphics g) { //draw mouse hover style border DrawBorder(g,2); //paint background PaintBack(g,SystemColors.ControlLightLight); } private void DrawMouseDownButton(Graphics g) { //draw mouse down style border DrawBorder(g,3); //paint background PaintBack(g,SystemColors.ControlLight); } private void DrawDisableButton(Graphics g) { //draw disable style border DrawBorder(g,4); //paint background PaintBack(g,SystemColors.ControlLight); } private void DrawContainFocusButton(Graphics g) { //draw contain focuse style border DrawBorder(g,5); //paint background PaintBack(g,SystemColors.ControlLightLight); } //paint background area of the button private void PaintBack(Graphics g,Color c) { g.FillRectangle(new SolidBrush(c),3,3, Width-6,Height-6); } private void WriteText(Graphics g) { //calculate the text position int x=0,y=0; Size s = g.MeasureString(Text,Font).ToSize(); x=(Width-s.Width)/2; y=(Height-s.Height)/2; //draw text if (Enabled) //is enabled, draw black text g.DrawString(Text,Font,Brushes.Black,x,y); else //not enabled, draw gray text g.DrawString(Text,Font,Brushes.Gray,x,y); } } }
3、在新控件的构造函数中添加:拖3个按钮到Form1上,将其中一个的"Enable"设为"false",右击鼠标,单击"View Code",在代码中用"MyButton"替换掉"System.Windows.Forms.Button";
4、编译执行。
最终,我们就得到了如图2所示的按钮控件。它可以在任何版本的windows操作系统上都保持一个样子。
图2 一个类似于Windows XP样式的按钮控件