diff --git a/WinFormControl/NButton.cs b/WinFormControl/NButton.cs
new file mode 100644
index 0000000..dab4825
--- /dev/null
+++ b/WinFormControl/NButton.cs
@@ -0,0 +1,350 @@
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Drawing;
+using System.Drawing.Drawing2D;
+using System.Drawing.Imaging;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows.Forms;
+
+namespace WinFormControl
+{
+ public class NButton : Button
+ {
+ private bool pulseOnFocus;
+
+ 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;
+
+ [DefaultValue(false)]
+ public bool WithStataHode { get; set; }
+
+ [DefaultValue(false)]
+ public bool SingleSelect { get; set; }
+
+ bool mAsClicked = false;
+
+ bool mDefaultSelected = false;
+ [DefaultValue(false)]
+ public bool DefaultSelected
+ {
+ get { return mDefaultSelected; }
+ set
+ {
+ if (mDefaultSelected == value)
+ return;
+ mDefaultSelected = value;
+ if (mDefaultSelected)
+ {
+ mAsClicked = true;
+ if (!WithStataHode)
+ WithStataHode = true;
+ }
+ if (mDefaultSelected)
+ mouseAction = MouseActionType.Hover;
+ else
+ mouseAction = MouseActionType.None;
+ Invalidate();
+ }
+ }
+
+ bool mEnableShadow = false;
+ [DefaultValue(false)]
+ public bool EnableShadow { get { return mEnableShadow; } set { mEnableShadow = value; Invalidate(); } }
+
+ bool mEnableCrystal = false;
+ [DefaultValue(false)]
+ public bool EnableCrystal { get { return mEnableCrystal; } set { mEnableCrystal = value; Invalidate(); } }
+
+ Color mToColoe = ColorTranslator.FromHtml("#3388FF");
+ public Color ToColor { get { return mToColoe; } set { mToColoe = value; Invalidate(); } }
+
+
+ Color mClickColor = Color.YellowGreen;
+ public Color ClickColor { get { return mClickColor; } set { mClickColor = value; } }
+
+ [Category("Sound"), Description("是否播放声音")]
+ public bool PlaySound { get; set; }
+
+ [Category("Sound"), Description("声音类型")]
+ public SoundType SoundType { get; set; }
+
+ public NButton()
+ {
+ mouseAction = MouseActionType.None;
+
+ this.SetStyle(ControlStyles.AllPaintingInWmPaint |
+ ControlStyles.DoubleBuffer |
+ ControlStyles.UserPaint, true);
+
+ this.ForeColor = Color.White;
+ this.BackColor = ColorTranslator.FromHtml("#3388FF");
+
+ gamma = 1.0f;
+ minGamma = 1.0f;
+ maxGamma = 2.2f;
+ gammaStep = 0.2f;
+ pulseTimer.Interval = 120;
+ pulseTimer.Tick += new EventHandler(pulseTimer_Tick);
+ }
+
+ [DefaultValue(false)]
+ public bool PulseOnFocus
+ {
+ get { return pulseOnFocus; }
+ set { pulseOnFocus = value; Invalidate(); }
+ }
+
+ private enum MouseActionType
+ {
+ None,
+ Hover,
+ Click
+ }
+
+ private MouseActionType mouseAction;
+
+ protected override void OnPaint(PaintEventArgs e)
+ {
+ Graphics g = e.Graphics;
+ g.Clear(this.Parent.BackColor);
+ Color clr = BackColor;
+ Color ed = ToColor;
+ int shadowOffset = 8;
+ int btnOffset = 0;
+ if (!Enabled)
+ {
+ clr = Color.DarkGray;
+ ed = clr;
+ }
+
+ switch (mouseAction)
+ {
+ case MouseActionType.Click:
+ shadowOffset = 4;
+ clr = ClickColor;
+ ed = clr;
+ btnOffset = 2;
+ break;
+ case MouseActionType.Hover:
+ clr = ClickColor;
+ ed = clr;
+ break;
+ }
+
+ g.SmoothingMode = SmoothingMode.AntiAlias;
+
+ ///
+ /// Create main colored shape
+ ///
+
+ var shadowDeep = EnableShadow ? 8 : 0;
+
+ Rectangle rc = new Rectangle(btnOffset, btnOffset, this.ClientSize.Width - shadowDeep - btnOffset, this.ClientSize.Height - shadowDeep - btnOffset);
+ GraphicsPath path1 = this.GetPath(rc, 15);
+ LinearGradientBrush br1 = new LinearGradientBrush(rc, clr, ed, LinearGradientMode.BackwardDiagonal);
+ ///
+ /// Create shadow
+ ///
+ if (EnableShadow)
+ {
+ Rectangle rc2 = rc;
+ rc2.Offset(shadowOffset, shadowOffset);
+ GraphicsPath path2 = this.GetPath(rc2, 15);
+ PathGradientBrush br2 = new PathGradientBrush(path2);
+ br2.CenterColor = ControlPaint.DarkDark(Color.Silver);
+ br2.SurroundColors = new Color[] { Color.White };
+ g.FillPath(br2, path2); //draw shadow
+ ///
+ }
+
+ g.FillPath(br1, path1); //draw main
+ ///
+ /// Create top water color to give "aqua " effect
+ ///
+ GraphicsPath path3 = null;
+ LinearGradientBrush br3 = null;
+ if (EnableCrystal)
+ {
+ Rectangle rc3 = rc;
+ rc3.Inflate(-5, -5);
+ rc3.Height = 15;
+ path3 = GetPath(rc3, 15);
+ br3 = new LinearGradientBrush(rc3, Color.FromArgb(255, Color.White), Color.FromArgb(0, Color.White), LinearGradientMode.Vertical);
+
+ ///
+ ///draw shapes
+ ///
+ 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
+ ///
+ Graphics g_bmp = null;
+ if (PulseOnFocus)
+ {
+ buttonBitmapRectangle = new Rectangle(rc.Location, rc.Size);
+ buttonBitmap = new Bitmap(buttonBitmapRectangle.Width, buttonBitmapRectangle.Height);
+ g_bmp = Graphics.FromImage(buttonBitmap);
+ g_bmp.SmoothingMode = SmoothingMode.AntiAlias;
+ g_bmp.FillPath(br1, path1);
+ if (EnableCrystal)
+ g_bmp.FillPath(br3, path3);
+ }
+
+
+
+ ///
+ /// Create a Path to draw the text to give the button a nice outline
+ ///
+
+ var textBrush = new LinearGradientBrush(this.ClientRectangle, this.ForeColor, this.ForeColor, LinearGradientMode.Vertical);
+
+ StringFormat drawFormat = new StringFormat();
+ drawFormat.LineAlignment = StringAlignment.Center;
+ drawFormat.Alignment = System.Drawing.StringAlignment.Center;
+
+ g.DrawString(this.Text, this.Font, textBrush, rc, drawFormat);
+ if (PulseOnFocus)
+ g_bmp.DrawString(this.Text, this.Font, textBrush, rc, drawFormat);
+ }
+
+ 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(new Point(e.X + Bounds.X, e.Y + Bounds.Y)))
+ // {
+ // //MessageBox.Show(string.Format("x:{0} y:{1}", e.X, e.Y));
+ // this.mouseAction = MouseActionType.Hover;
+ // }
+ // else
+ // this.mouseAction = MouseActionType.None;
+ // this.Invalidate();
+ // base.OnMouseUp(e);
+ //}
+
+ protected override void OnClick(EventArgs e)
+ {
+ this.Enabled = false;
+ if (PlaySound)
+ SoundPalyUtil.PlaySound(SoundType);
+ try
+ {
+ base.OnClick(e);
+ }
+ catch {
+ Application.DoEvents();
+ this.Enabled = true;
+ mouseAction = MouseActionType.Hover;
+ this.Invalidate();
+ this.Focus();
+ throw;
+ }
+
+
+ if (SingleSelect)
+ {
+ foreach (var ctl in Parent.Controls)
+ {
+ var btn = ctl as NButton;
+ if (btn == null)
+ continue;
+ if (btn.Text == this.Text)
+ {
+ if (WithStataHode)
+ continue;
+ else
+ mAsClicked = !mAsClicked;
+ }
+ if (btn.mAsClicked)
+ {
+ btn.mAsClicked = false;
+ btn.mouseAction = MouseActionType.None;
+ btn.Invalidate();
+ }
+ }
+ }
+
+ if (WithStataHode)
+ this.mAsClicked = !mAsClicked;
+ if (mAsClicked)
+ this.mouseAction = MouseActionType.Hover;
+ else
+ this.mouseAction = MouseActionType.None;
+ Application.DoEvents();
+ this.Enabled = true;
+ // this.Invalidate();
+ this.Focus();
+ }
+
+ protected override void OnMouseLeave(EventArgs e)
+ {
+ if (!mAsClicked)
+ {
+ this.mouseAction = MouseActionType.None;
+ this.Invalidate();
+ }
+ base.OnMouseLeave(e);
+ }
+
+ 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();
+ }
+
+ 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);
+ }
+ }
+ }
+}
diff --git a/WinFormControl/WinFormControl.csproj b/WinFormControl/WinFormControl.csproj
index 20b07d5..2a9c169 100644
--- a/WinFormControl/WinFormControl.csproj
+++ b/WinFormControl/WinFormControl.csproj
@@ -45,6 +45,9 @@
+
+ Component
+
UserControl