用过QQ2009的网友都知道QQ主面板的界面非常炫丽,特别好看,鼠标移上去还有淡入淡出的效果。那这样效果是怎么做出来的呢?其实不难,只要自定义一个用户控件的外怪就可以了,用到GDI+技术和时钟控件来操作…
首先我们在VS2008里面新建一个Windows窗体控件库的项目,系统会自动生成一个用户控件UserControl1.cs出来,我们就用默认的名字吧~~
本例子下载地址:https://files.cnblogs.com/mengxin523/自定义按钮控件.rar
程序所有代码如下:
using System;
using System.Data;
using System.Drawing;
using System.Collections;
using System.Windows.Forms;
using System.ComponentModel;
using System.Drawing.Drawing2D;
namespace MyButton
{
public partial class UserControl1 : UserControl
{
private bool calledbykey = false;
private State mButtonState = State.None; //按钮的状态
private Timer mFadeIn = new Timer(); //淡入的时钟
private Timer mFadeOut = new Timer(); //淡出的时钟
private int mGlowAlpha = 0; //透明度
private System.ComponentModel.Container components = null;
public UserControl1()
{
InitializeComponent();
//一下几个语句是对控件进行设置和对GDI+进行优化
this.SetStyle(ControlStyles.AllPaintingInWmPaint, true);
this.SetStyle(ControlStyles.DoubleBuffer, true);
this.SetStyle(ControlStyles.OptimizedDoubleBuffer, true);
this.SetStyle(ControlStyles.ResizeRedraw, true);
this.SetStyle(ControlStyles.Selectable, true);
this.SetStyle(ControlStyles.SupportsTransparentBackColor, true);
this.SetStyle(ControlStyles.UserPaint, true);
this.UpdateStyles();
this.BackColor = Color.Transparent; //设置控件背景色透明
mFadeIn.Interval = 20; //淡入速度
mFadeOut.Interval = 20; //淡出速度
}
protected override void Dispose(bool disposing)
{
if (disposing)
{
if (components != null)
{
components.Dispose();
}
}
base.Dispose(disposing);
}
private void InitializeComponent()
{
this.Name = "MySystemButton";
this.Size = new System.Drawing.Size(100, 32);
this.Paint += new System.Windows.Forms.PaintEventHandler(this.VistaButton_Paint);
this.KeyUp += new System.Windows.Forms.KeyEventHandler(this.VistaButton_KeyUp);
this.KeyDown += new System.Windows.Forms.KeyEventHandler(this.VistaButton_KeyDown);
this.MouseEnter += new System.EventHandler(this.VistaButton_MouseEnter);
this.MouseLeave += new System.EventHandler(this.VistaButton_MouseLeave);
this.MouseUp += new MouseEventHandler(VistaButton_MouseUp);
this.MouseDown += new System.Windows.Forms.MouseEventHandler(this.VistaButton_MouseDown);
this.GotFocus += new EventHandler(VistaButton_MouseEnter);
this.LostFocus += new EventHandler(VistaButton_MouseLeave);
this.mFadeIn.Tick += new EventHandler(mFadeIn_Tick);
this.mFadeOut.Tick += new EventHandler(mFadeOut_Tick);
this.Resize += new EventHandler(VistaButton_Resize);
}
/// <summary>
/// 按钮的样式
/// </summary>
public enum Style
{
/// <summary>
/// Draw the button as normal
/// </summary>
Default,
/// <summary>
/// Only draw the background on mouse over.
/// </summary>
Flat
};
/// <summary>
/// 用于设置按钮的用处
/// </summary>
public enum UseTo
{
Min, Close
};
UseTo Ut = UseTo.Close; //默认作为关闭按钮
[Category("UseTo"),
DefaultValue(UseTo.Close),
Browsable(true),
Description("设置按钮的用处")]
public
{
get
{
return Ut;
}
set
{
Ut = value;
this.Invalidate();
}
}
private string mText;
/// <summary>
/// 按钮上显示的文本
/// </summary>
[Category("Text"),
Description("按钮上显示的文本.")]
public string ButtonText
{
get { return mText; }
set { mText = value; this.Invalidate(); }
}
private Color mForeColor = Color.White;
/// <summary>
/// 文本颜色
/// </summary>
[Category("Text"),
Browsable(true),
DefaultValue(typeof(Color), "White"),
Description("文本颜色.")]
public override Color ForeColor
{
get { return mForeColor; }
set { mForeColor = value; this.Invalidate(); }
}
private ContentAlignment mTextAlign = ContentAlignment.MiddleCenter;
/// <summary>
/// 文本对齐方式
/// </summary>
[Category("Text"),
DefaultValue(typeof(ContentAlignment), "MiddleCenter")]
public ContentAlignment TextAlign
{
get { return mTextAlign; }
set { mTextAlign = value; this.Invalidate(); }
}
private Image mImage;
/// <summary>
按钮上的图片
/// </summary>
[Category("Image"),
DefaultValue(null)]
public Image Image
{
get { return mImage; }
set { mImage = value; this.Invalidate(); }
}
private ContentAlignment mImageAlign = ContentAlignment.MiddleLeft;
/// <summary>
按钮对齐方式
/// </summary>
[Category("Image"),
DefaultValue(typeof(ContentAlignment), "MiddleLeft")]
public ContentAlignment ImageAlign
{
get { return mImageAlign; }
set { mImageAlign = value; this.Invalidate(); }
}
private Size mImageSize = new Size(24, 24);
/// <summary>
图片大小
/// </summary>
[Category("Image"),
DefaultValue(typeof(Size), "24, 24")]
public Size ImageSize
{
get { return mImageSize; }
set { mImageSize = value; this.Invalidate(); }
}
private Style mButtonStyle = Style.Default;
/// <summary>
按钮的样式
/// </summary>
[Category("Appearance"),
DefaultValue(typeof(Style), "Default")]
public Style ButtonStyle
{
get { return mButtonStyle; }
set { mButtonStyle = value; this.Invalidate(); }
}
private int mCornerRadius = 3;
/// <summary>
按钮边角的曲度
/// </summary>
[Category("Appearance"),
DefaultValue(8)]
public int CornerRadius
{
get { return mCornerRadius; }
set { mCornerRadius = value; this.Invalidate(); }
}
private Color mHighlightColor = Color.Gray;
/// <summary>
高亮的颜色
/// </summary>
[Category("Appearance"),
DefaultValue(typeof(Color), "White")]
public Color HighlightColor
{
get { return mHighlightColor; }
set { mHighlightColor = value; this.Invalidate(); }
}
private Color mButtonColor = Color.Black;
/// <summary>
/// The bottom color of the button that
/// will be drawn over the base color.
/// </summary>
[Category("Appearance"),
DefaultValue(typeof(Color), "Black")]
public Color ButtonColor
{
get { return mButtonColor; }
set { mButtonColor = value; this.Invalidate(); }
}
private Color mGlowColor = Color.FromArgb(141, 189, 255);
/// <summary>
/// 鼠标移上去之后显示的颜色
/// </summary>
[Category("Appearance"),
DefaultValue(typeof(Color), "141,189,255")]
public Color GlowColor
{
get { return mGlowColor; }
set { mGlowColor = value; this.Invalidate(); }
}
private Image mBackImage;
/// <summary>
背景图片
/// </summary>
[Category("Appearance"),
DefaultValue(null)]
public Image BackImage
{
get { return mBackImage; }
set { mBackImage = value; this.Invalidate(); }
}
private static Color mBaseColor = Color.Black;
/// <summary>
/// The backing color that the rest of
/// the button is drawn. For a glassier
/// effect set this property to Transparent.
/// </summary>
[Category("Appearance"),
DefaultValue(typeof(Color), "Black")]
public Color BaseColor
{
get { return mBaseColor; }
set { mBaseColor = value; this.Invalidate(); }
}
/// <summary>
/// 按钮的形状
/// </summary>
/// <param name="r"></param>
/// <param name="r1"></param>
/// <param name="r2"></param>
/// <param name="r3"></param>
/// <param name="r4"></param>
/// <returns></returns>
private GraphicsPath RoundRect(RectangleF r, float r1, float r2, float r3, float r4)
{
float x = r.X, y = r.Y, w = r.Width, h = r.Height;
GraphicsPath rr = new GraphicsPath();
rr.AddBezier(x, y + r1, x, y, x + r1, y, x + r1, y);
rr.AddLine(x + r1, y, x + w - r2, y);
rr.AddBezier(x + w - r2, y, x + w, y, x + w, y + r2, x + w, y + r2);
rr.AddLine(x + w, y + r2, x + w, y + h - r3);
rr.AddBezier(x + w, y + h - r3, x + w, y + h, x + w - r3, y + h, x + w - r3, y + h);
rr.AddLine(x + w - r3, y + h, x + r4, y + h);
rr.AddBezier(x + r4, y + h, x, y + h, x, y + h - r4, x, y + h - r4);
rr.AddLine(x, y + h - r4, x, y + r1);
return rr;
}
/// <summary>
/// 对齐方式
/// </summary>
/// <param name="textalign"></param>
/// <returns></returns>
private StringFormat StringFormatAlignment(ContentAlignment textalign)
{
StringFormat sf = new StringFormat();
switch (textalign)
{
case ContentAlignment.TopLeft:
case ContentAlignment.TopCenter:
case ContentAlignment.TopRight:
sf.LineAlignment = StringAlignment.Near;
break;
case ContentAlignment.MiddleLeft:
case ContentAlignment.MiddleCenter:
case ContentAlignment.MiddleRight:
sf.LineAlignment = StringAlignment.Center;
break;
case ContentAlignment.BottomLeft:
case ContentAlignment.BottomCenter:
case ContentAlignment.BottomRight:
sf.LineAlignment = StringAlignment.Far;
break;
}
switch (textalign)
{
case ContentAlignment.TopLeft:
case ContentAlignment.MiddleLeft:
case ContentAlignment.BottomLeft:
sf.Alignment = StringAlignment.Near;
break;
case ContentAlignment.TopCenter:
case ContentAlignment.MiddleCenter:
case ContentAlignment.BottomCenter:
sf.Alignment = StringAlignment.Center;
break;
case ContentAlignment.TopRight:
case ContentAlignment.MiddleRight:
case ContentAlignment.BottomRight:
sf.Alignment = StringAlignment.Far;
break;
}
return sf;
}
/// <summary>
/// 画出按钮的外框线条
/// </summary>
/// <param name="g">The graphics object used in the paint event.</param>
private void DrawOuterStroke(Graphics g)
{
if (this.ButtonStyle == Style.Flat && this.mButtonState == State.None) { return; }
Rectangle r = this.ClientRectangle;
r.Width -= 1; r.Height -= 1;
using (GraphicsPath rr = RoundRect(r, CornerRadius, CornerRadius, CornerRadius, CornerRadius)) //圆角矩形
{
using (Pen p = new Pen(this.ButtonColor))
{
g.DrawPath(p, rr); //画出外框
}
}
}
/// <summary>
/// 画出按钮的内框线条
/// </summary>
/// <param name="g">The graphics object used in the paint event.</param>
private void DrawInnerStroke(Graphics g)
{
if (this.ButtonStyle == Style.Flat && this.mButtonState == State.None) { return; }
Rectangle r = this.ClientRectangle;
r.X++; r.Y++;
r.Width -= 3; r.Height -= 3;
using (GraphicsPath rr = RoundRect(r, CornerRadius, CornerRadius, CornerRadius, CornerRadius))
{
using (Pen p = new Pen(this.HighlightColor))
{
g.DrawPath(p, rr);
}
}
}
/// <summary>
/// 画出按钮的背景
/// </summary>
/// <param name="g">The graphics object used in the paint event.</param>
private void DrawBackground(Graphics g)
{
if (this.ButtonStyle == Style.Flat && this.mButtonState == State.None) { return; }
int alpha = (mButtonState == State.Pressed) ? 204 : 127;
Rectangle r = this.ClientRectangle;
r.Width--; r.Height--;
using (GraphicsPath rr = RoundRect(r, CornerRadius, CornerRadius, CornerRadius, CornerRadius))
{
using (SolidBrush sb = new SolidBrush(this.BaseColor))
{
g.FillPath(sb, rr);
}
if (this.BackImage != null) { g.DrawImage(this.BackImage, this.ClientRectangle); }
g.ResetClip();
using (SolidBrush sb = new SolidBrush(Color.FromArgb(alpha, this.ButtonColor)))
{
g.FillPath(sb, rr);
}
}
}
/// <summary>
/// 画出按钮的上半部分高光颜色
/// </summary>
/// <param name="g">The graphics object used in the paint event.</param>
private void DrawHighlight(Graphics g)
{
if (this.ButtonStyle == Style.Flat && this.mButtonState == State.None) { return; }
int alpha = (mButtonState == State.Pressed) ? 60 : 150;
Rectangle rect = new Rectangle(0, 0, this.Width, this.Height / 2);
using (GraphicsPath r = RoundRect(rect, CornerRadius, CornerRadius, 0, 0))
{
using (LinearGradientBrush lg = new LinearGradientBrush(r.GetBounds(),
Color.FromArgb(alpha, this.HighlightColor),
Color.FromArgb(alpha / 3, this.HighlightColor),
LinearGradientMode.Vertical))
{
g.FillPath(lg, r);
}
}
}
/// <summary>
/// 当鼠标移上去的时候的炫光
/// </summary>
/// <param name="g">The graphics object used in the paint event.</param>
private void DrawGlow(Graphics g)
{
if (this.mButtonState == State.Pressed) { return; }
using (GraphicsPath glow = new GraphicsPath())
{
Rectangle r = this.ClientRectangle;
//r.Width -= 3; r.Height -= 3;
glow.AddPath(RoundRect(new Rectangle(r.Left + 1, r.Top + 1, r.Width - 3, r.Height - 3), CornerRadius, CornerRadius, CornerRadius, CornerRadius), true);
using (GraphicsPath gp = RoundRect(new Rectangle(r.Left + 1, r.Top + 1, r.Width - 3, r.Height / 2 - 2), CornerRadius, CornerRadius, CornerRadius, CornerRadius))
{
Color c = Color.FromArgb(mGlowAlpha, this.GlowColor);
Color c1 = Color.FromArgb(mGlowAlpha / 2 + 50, Color.White);
using (SolidBrush sb = new SolidBrush(c))
{
using (SolidBrush sb1 = new SolidBrush(c1))
{
g.FillPath(sb, glow);
g.FillPath(sb1, gp);
}
}
}
}
g.ResetClip();
}
/// <summary>
/// 显示按钮的文本
/// </summary>
/// <param name="g">The graphics object used in the paint event.</param>
private void DrawText(Graphics g)
{
StringFormat sf = StringFormatAlignment(this.TextAlign);
Rectangle r = new Rectangle(8, 8, this.Width - 17, this.Height - 17);
g.DrawString(this.ButtonText, this.Font, new SolidBrush(this.ForeColor), r, sf);
}
/// <summary>
/// 画出按钮上的图标
/// </summary>
/// <param name="g"></param>
private void DrawIcon(Graphics g)
{
if (this.UT == UseTo.Close)
{
//关闭图片
}
else if (this.UT == UseTo.Min)
{
//最小化的图片
}
}
private void VistaButton_Paint(object sender, PaintEventArgs e)
{
Graphics g = e.Graphics;
g.SmoothingMode = SmoothingMode.AntiAlias;
g.InterpolationMode = InterpolationMode.HighQualityBicubic;
DrawBackground(g);
DrawHighlight(g);
DrawGlow(g);
DrawIcon(g);
DrawInnerStroke(g);
}
private void VistaButton_Resize(object sender, EventArgs e)
{
Rectangle r = this.ClientRectangle;
r.X -= 1; r.Y -= 1;
r.Width += 2; r.Height += 2;
using (GraphicsPath rr = RoundRect(r, CornerRadius, CornerRadius, CornerRadius, CornerRadius))
{
this.Region = new Region(rr);
}
}
private void VistaButton_MouseEnter(object sender, EventArgs e)
{
mButtonState = State.Hover;
mFadeOut.Stop();
mFadeIn.Start();
}
private void VistaButton_MouseLeave(object sender, EventArgs e)
{
mButtonState = State.None;
if (this.mButtonStyle == Style.Flat) { mGlowAlpha = 0; }
mFadeIn.Stop();
mFadeOut.Start();
}
private void VistaButton_MouseDown(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Left)
{
mButtonState = State.Pressed;
if (this.mButtonStyle != Style.Flat) { mGlowAlpha = 255; }
mFadeIn.Stop();
mFadeOut.Stop();
this.Invalidate();
}
}
private void mFadeIn_Tick(object sender, EventArgs e)
{
if (this.ButtonStyle == Style.Flat) { mGlowAlpha = 0; }
if (mGlowAlpha + 30 >= 255)
{
mGlowAlpha = 255;
mFadeIn.Stop();
}
else
{
mGlowAlpha += 30;
}
this.Invalidate();
}
private void mFadeOut_Tick(object sender, EventArgs e)
{
if (this.ButtonStyle == Style.Flat) { mGlowAlpha = 0; }
if (mGlowAlpha - 30 <= 0)
{
mGlowAlpha = 0;
mFadeOut.Stop();
}
else
{
mGlowAlpha -= 30;
}
this.Invalidate();
}
private void VistaButton_KeyDown(object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.Space)
{
MouseEventArgs m = new MouseEventArgs(MouseButtons.Left, 0, 0, 0, 0);
VistaButton_MouseDown(sender, m);
}
}
private void VistaButton_KeyUp(object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.Space)
{
MouseEventArgs m = new MouseEventArgs(MouseButtons.Left, 0, 0, 0, 0);
calledbykey = true;
VistaButton_MouseUp(sender, m);
}
}
private void VistaButton_MouseUp(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Left)
{
mButtonState = State.Hover;
mFadeIn.Stop();
mFadeOut.Stop();
this.Invalidate();
if (calledbykey == true) { this.OnClick(EventArgs.Empty); calledbykey = false; }
}
}
}
}