.
在WinForm中有很多元件可能現有可以變更的樣式很少,或是可能會完全無法變更
如果想要變更就需要重新繪製元件,並定義所需要的屬性
以本篇來說,一般的按鍵四邊都是偏稜角,本身也只有字型跟底色可以選擇
如果要讓按鍵看起來更華麗,則需要重繪
以下為重繪按鍵實作範例
定義 AquaButton 類別 繼承 Button 進行重繪
相關連結
- using System;
- using System.Windows.Forms;
- using System.Drawing;
- using System.Drawing.Drawing2D;
- using System.Diagnostics;
- using System.Drawing.Imaging;
- using System.ComponentModel;
-
- namespace AquaButtonTester
- {
- /// <summary>
- /// Summary description for AquaButton.
- /// </summary>
- [Serializable]
- public class AquaButton : System.Windows.Forms.Button
- {
- /// <summary>
- /// Required designer variable.
- /// </summary>
- private System.ComponentModel.Container components = null;
- private bool pulseOnFocus;
-
- ///
- ///Additional variables to handle pulsing
- ///
- private ImageAttributes imgAttr = new ImageAttributes();
- private float gamma;
- private float minGamma;
- private float maxGamma;
- private float gammaStep;
- private Timer pulseTimer = new Timer();
- private Bitmap buttonBitmap;
- private Rectangle buttonBitmapRectangle;
-
- public AquaButton()
- {
- // This call is required by the Windows.Forms Form Designer.
- InitializeComponent();
-
- mouseAction = MouseActionType.None;
-
- this.SetStyle(ControlStyles.AllPaintingInWmPaint |
- ControlStyles.DoubleBuffer |
- ControlStyles.UserPaint, true);
-
- //The following defaults are better suited to draw the text outline
- this.Font = new Font("Arial Black", 12, FontStyle.Bold);
- this.BackColor = Color.DarkTurquoise;
- this.Size = new Size(112, 48);
-
- //Initialize variables to Pulse button
- gamma = 1.0f;
- minGamma = 1.0f;
- maxGamma = 2.2f;
- gammaStep = .2f;
- pulseTimer.Interval = 90;
- pulseTimer.Tick +=new EventHandler(pulseTimer_Tick);
- }
-
- [DefaultValue(false)]
- public bool PulseOnFocus
- {
- get { return pulseOnFocus; }
- set { pulseOnFocus = value; Invalidate(); }
- }
-
-
- /// <summary>
- /// Clean up any resources being used.
- /// </summary>
- protected override void Dispose( bool disposing )
- {
- if( disposing )
- {
- if(components != null)
- {
- components.Dispose();
- }
- }
- base.Dispose( disposing );
- }
-
- #region Component Designer generated code
- /// <summary>
- /// Required method for Designer support - do not modify
- /// the contents of this method with the code editor.
- /// </summary>
- private void InitializeComponent()
- {
- components = new System.ComponentModel.Container();
- }
- #endregion
-
- private enum MouseActionType
- {
- None,
- Hover,
- Click
- }
-
- private MouseActionType mouseAction;
-
- protected override void OnPaint(PaintEventArgs e)
- {
- Graphics g = e.Graphics;
- g.Clear(Color.White);
- Color clr = this.BackColor;
- int shadowOffset = 8;
- int btnOffset = 0;
- switch (mouseAction)
- {
- case MouseActionType.Click:
- shadowOffset = 4;
- clr = Color.Gold;
- btnOffset = 2;
- break;
- case MouseActionType.Hover:
- clr = Color.Gold;
- break;
- }
- g.SmoothingMode = SmoothingMode.AntiAlias;
-
- ///
- /// Create main colored shape
- ///
- Rectangle rc = new Rectangle(btnOffset,btnOffset,this.ClientSize.Width-8-
- btnOffset, this.ClientSize.Height-8-btnOffset);
- GraphicsPath path1 = this.GetPath(rc, 20);
- LinearGradientBrush br1 = new LinearGradientBrush(new Point(0, 0),new
- Point(0, rc.Height+6), clr, Color.White);
-
- ///
- /// Create shadow
- ///
- Rectangle rc2 = rc;
- rc2.Offset(shadowOffset, shadowOffset);
- GraphicsPath path2 = this.GetPath(rc2, 20);
- PathGradientBrush br2 = new PathGradientBrush(path2);
- br2.CenterColor = ControlPaint.DarkDark(Color.Silver);
- br2.SurroundColors = new Color[]{Color.White};
-
- ///
- /// Create top water color to give "aqua" effect
- ///
- Rectangle rc3 = rc;
- rc3.Inflate(-5, -5);
- rc3.Height = 15;
- GraphicsPath path3 = GetPath(rc3, 20);
- LinearGradientBrush br3 = new LinearGradientBrush(rc3, Color.FromArgb(255,
- Color.White), Color.FromArgb(0, Color.White), LinearGradientMode.Vertical);
-
- ///
- ///draw shapes
- ///
- g.FillPath(br2, path2); //draw shadow
- g.FillPath(br1, path1); //draw main
- g.FillPath(br3, path3); //draw top bubble
-
- ///
- ///Create a backup of the button image to a bitmap so we can manipulate it's
- pulsing action
- ///
- buttonBitmapRectangle = new Rectangle(rc.Location, rc.Size);
- buttonBitmap = new Bitmap(buttonBitmapRectangle.Width,
- buttonBitmapRectangle.Height);
- Graphics g_bmp = Graphics.FromImage(buttonBitmap);
- g_bmp.SmoothingMode = SmoothingMode.AntiAlias;
- g_bmp.FillPath(br1, path1);
- g_bmp.FillPath(br3, path3);
-
- ///
- ///Set the region for the button
- Region rgn = new Region(path1);
- rgn.Union(path2);
- this.Region = rgn;
-
- ///
- /// Create a Path to draw the text to give the button a nice outline
- ///
- GraphicsPath path4 = new GraphicsPath();
-
- RectangleF path1bounds = path1.GetBounds();
- Rectangle rcText = new Rectangle((int)path1bounds.X, (int)path1bounds.Y,
- (int)path1bounds.Width, (int)path1bounds.Height);
-
- StringFormat strformat = new StringFormat();
- strformat.Alignment = StringAlignment.Center;
- strformat.LineAlignment = StringAlignment.Center;
- path4.AddString(this.Text, this.Font.FontFamily, (int)this.Font.Style,
- this.Font.Size, rcText, strformat);
-
- Pen txtPen = new Pen(this.ForeColor, 1);
- g.DrawPath(txtPen, path4);
- g_bmp.DrawPath(txtPen, path4);
- }
- private GraphicsPath GetPath(Rectangle rc, int r)
- {
- int x = rc.X, y = rc.Y, w = rc.Width, h = rc.Height;
- GraphicsPath path = new GraphicsPath();
- path.AddArc(x, y, r, r, 180, 90); //Upper left corner
- path.AddArc(x+w - r, y, r, r, 270, 90); //Upper right corner
- path.AddArc(x+w - r, y+h - r, r, r, 0, 90); //Lower right corner
- path.AddArc(x, y+h - r, r, r, 90, 90); //Lower left corner
- path.CloseFigure();
- return path;
- }
-
- protected override void OnMouseDown(MouseEventArgs e)
- {
- if (e.Button == MouseButtons.Left)
- {
- this.mouseAction = MouseActionType.Click;
- this.Invalidate();
- }
- base.OnMouseDown (e);
- }
-
- protected override void OnMouseUp(MouseEventArgs e)
- {
- if (this.Bounds.Contains(e.X, e.Y))
- this.mouseAction = MouseActionType.Hover;
- else
- this.mouseAction = MouseActionType.None;
- this.Invalidate();
- base.OnMouseUp (e);
- }
-
-
- protected override void OnMouseEnter(EventArgs e)
- {
- this.mouseAction = MouseActionType.Hover;
- this.Invalidate();
- base.OnMouseEnter (e);
- }
-
- protected override void OnMouseLeave(EventArgs e)
- {
- this.mouseAction = MouseActionType.None;
- this.Invalidate();
- base.OnMouseLeave (e);
- }
-
- //-----------------------------------------------------------------
- // METHODS TO HANDLE PULSING
- //-----------------------------------------------------------------
-
- protected override void OnGotFocus(EventArgs e)
- {
- base.OnGotFocus (e);
- if (this.pulseOnFocus)
- pulseTimer.Start();
- }
-
- protected override void OnLostFocus(EventArgs e)
- {
- base.OnLostFocus (e);
- pulseTimer.Stop();
- this.Invalidate(); //redraw to get back it's original picture
- }
-
- private void pulseTimer_Tick(object sender, EventArgs e)
- {
- if (this.Focused && pulseOnFocus && buttonBitmap != null)
- {
- gamma += gammaStep;
- if (gamma > this.maxGamma) gammaStep = - gammaStep;
- if (gamma < this.minGamma) gammaStep = Math.Abs(gammaStep);
- imgAttr.SetGamma(gamma);
- this.CreateGraphics().DrawImage(buttonBitmap,
- buttonBitmapRectangle, 0, 0,
- buttonBitmap.Width, buttonBitmap.Height, GraphicsUnit.Pixel, imgAttr);
- }
- }
- }
- }
接著主程式直接使用定義好的按鍵
宣告定義的按鍵型別並使用
- using System;
- using System.Drawing;
- using System.Collections;
- using System.ComponentModel;
- using System.Windows.Forms;
- using System.Data;
-
- namespace AquaButtonTester
- {
- /// <summary>
- /// Summary description for Form1.
- /// </summary>
- public class Form1 : System.Windows.Forms.Form
- {
- private AquaButtonTester.AquaButton aquaButton1;
- private AquaButtonTester.AquaButton aquaButton2;
- private AquaButtonTester.AquaButton aquaButton3;
- private AquaButtonTester.AquaButton aquaButton4;
- private AquaButtonTester.AquaButton aquaButton5;
- private AquaButtonTester.AquaButton aquaButton6;
- /// <summary>
- /// Required designer variable.
- /// </summary>
- private System.ComponentModel.Container components = null;
-
- public Form1()
- {
- //
- // Required for Windows Form Designer support
- //
- InitializeComponent();
-
- //
- // TODO: Add any constructor code after InitializeComponent call
- //
- }
-
- /// <summary>
- /// Clean up any resources being used.
- /// </summary>
- protected override void Dispose( bool disposing )
- {
- if( disposing )
- {
- if (components != null)
- {
- components.Dispose();
- }
- }
- base.Dispose( disposing );
- }
-
- #region Windows Form Designer generated code
- /// <summary>
- /// Required method for Designer support - do not modify
- /// the contents of this method with the code editor.
- /// </summary>
- private void InitializeComponent()
- {
- this.aquaButton1 = new AquaButtonTester.AquaButton();
- this.aquaButton2 = new AquaButtonTester.AquaButton();
- this.aquaButton3 = new AquaButtonTester.AquaButton();
- this.aquaButton4 = new AquaButtonTester.AquaButton();
- this.aquaButton5 = new AquaButtonTester.AquaButton();
- this.aquaButton6 = new AquaButtonTester.AquaButton();
- this.SuspendLayout();
- //
- // aquaButton1
- //
- this.aquaButton1.BackColor = System.Drawing.Color.DarkTurquoise;
- this.aquaButton1.Font = new System.Drawing.Font("Arial Black", 12F,
- System.Drawing.FontStyle.Bold);
- this.aquaButton1.Location = new System.Drawing.Point(19, 22);
- this.aquaButton1.Name = "aquaButton1";
- this.aquaButton1.PulseOnFocus = true;
- this.aquaButton1.Size = new System.Drawing.Size(135, 67);
- this.aquaButton1.TabIndex = 0;
- this.aquaButton1.Text = "Button 1";
- this.aquaButton1.UseVisualStyleBackColor = false;
- this.aquaButton1.Click += new System.EventHandler(this.aquaButton_Click);
- //
- // aquaButton2
- //
- this.aquaButton2.BackColor = System.Drawing.Color.Tomato;
- this.aquaButton2.Font = new System.Drawing.Font("Arial Black", 12F,
- System.Drawing.FontStyle.Bold);
- this.aquaButton2.Location = new System.Drawing.Point(182, 22);
- this.aquaButton2.Name = "aquaButton2";
- this.aquaButton2.Size = new System.Drawing.Size(135, 67);
- this.aquaButton2.TabIndex = 1;
- this.aquaButton2.Text = "Button 2";
- this.aquaButton2.UseVisualStyleBackColor = false;
- this.aquaButton2.Click += new System.EventHandler(this.aquaButton_Click);
- //
- // aquaButton3
- //
- this.aquaButton3.BackColor = System.Drawing.Color.RosyBrown;
- this.aquaButton3.Font = new System.Drawing.Font("Arial Black", 12F,
- System.Drawing.FontStyle.Bold);
- this.aquaButton3.Location = new System.Drawing.Point(19, 100);
- this.aquaButton3.Name = "aquaButton3";
- this.aquaButton3.PulseOnFocus = true;
- this.aquaButton3.Size = new System.Drawing.Size(135, 66);
- this.aquaButton3.TabIndex = 3;
- this.aquaButton3.Text = "Button 3";
- this.aquaButton3.UseVisualStyleBackColor = false;
- this.aquaButton3.Click += new System.EventHandler(this.aquaButton_Click);
- //
- // aquaButton4
- //
- this.aquaButton4.BackColor = System.Drawing.Color.DodgerBlue;
- this.aquaButton4.Font = new System.Drawing.Font("Arial Black", 12F,
- System.Drawing.FontStyle.Bold);
- this.aquaButton4.Location = new System.Drawing.Point(182, 100);
- this.aquaButton4.Name = "aquaButton4";
- this.aquaButton4.Size = new System.Drawing.Size(135, 66);
- this.aquaButton4.TabIndex = 2;
- this.aquaButton4.Text = "Button 4";
- this.aquaButton4.UseVisualStyleBackColor = false;
- this.aquaButton4.Click += new System.EventHandler(this.aquaButton_Click);
- //
- // aquaButton5
- //
- this.aquaButton5.BackColor = System.Drawing.Color.MediumSeaGreen;
- this.aquaButton5.Font = new System.Drawing.Font("Arial Black", 12F,
- System.Drawing.FontStyle.Bold);
- this.aquaButton5.Location = new System.Drawing.Point(19, 188);
- this.aquaButton5.Name = "aquaButton5";
- this.aquaButton5.PulseOnFocus = true;
- this.aquaButton5.Size = new System.Drawing.Size(135, 67);
- this.aquaButton5.TabIndex = 1;
- this.aquaButton5.Text = "Button 5";
- this.aquaButton5.UseVisualStyleBackColor = false;
- this.aquaButton5.Click += new System.EventHandler(this.aquaButton_Click);
- //
- // aquaButton6
- //
- this.aquaButton6.BackColor = System.Drawing.Color.Violet;
- this.aquaButton6.Font = new System.Drawing.Font("Arial Black", 12F,
- System.Drawing.FontStyle.Bold);
- this.aquaButton6.Location = new System.Drawing.Point(182, 188);
- this.aquaButton6.Name = "aquaButton6";
- this.aquaButton6.Size = new System.Drawing.Size(135, 67);
- this.aquaButton6.TabIndex = 0;
- this.aquaButton6.Text = "Button 6";
- this.aquaButton6.UseVisualStyleBackColor = false;
- this.aquaButton6.Click += new System.EventHandler(this.aquaButton_Click);
- //
- // Form1
- //
- this.AcceptButton = this.aquaButton2;
- this.AutoScaleBaseSize = new System.Drawing.Size(6, 18);
- this.BackColor = System.Drawing.Color.White;
- this.ClientSize = new System.Drawing.Size(433, 316);
- this.Controls.Add(this.aquaButton6);
- this.Controls.Add(this.aquaButton5);
- this.Controls.Add(this.aquaButton4);
- this.Controls.Add(this.aquaButton3);
- this.Controls.Add(this.aquaButton2);
- this.Controls.Add(this.aquaButton1);
- this.Name = "Form1";
- this.Text = "AquaButton Demo";
- this.Load += new System.EventHandler(this.Form1_Load);
- this.ResumeLayout(false);
-
- }
- #endregion
-
- /// <summary>
- /// The main entry point for the application.
- /// </summary>
- [STAThread]
- static void Main()
- {
- Application.Run(new Form1());
- }
-
- private void aquaButton_Click(object sender, System.EventArgs e)
- {
- Button btn = (Button) sender;
- MessageBox.Show("You clicked " + btn.Name);
- }
-
- private void Form1_Load(object sender, System.EventArgs e)
- {
- this.aquaButton1.Focus();
- }
- }
- }
執行結果
載入時每個按鍵呈現定義好的顏色與樣式
當選取 button1時,呈現黃底色
按下觸發事件
選取 button2時呈現黃底色
按下觸發事件
選取 button3時呈現黃底色
功能依此類推
可以依據想要的顏色與樣式對程式碼進行變更