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