| @ -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); | |||||
| } | |||||
| } | |||||
| } | |||||
| } | |||||