如何重畫Windows控件[轉]

如何重畫Windows控件

本文內容:
  • 概述
  • 平臺需求
  • 例1:改變控件屬性
  • 例2:重畫簡單控件

概述:
當你在全新體驗Windows XP令人賞心悅目的界面的時候,你一定在想"如果我的程序界面也都能這麼漂亮,那該多好啊"。那就讓我們來看看到底應該如何通過.NET類庫來重畫Windows標準控件。
本文通過兩個例子來闡述如何通過程序編碼來有效的改變Windows標準控件外觀。

平臺需求:
  • Visual Studio .NET
  • Visual C# .NET

例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樣式的按鈕控件

作者:韓定一
2002年7月23日

from : http://www.microsoft.com/China/Community/program/originalarticles/TechDoc/redrawcomponent.mspx
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章