using System.ComponentModel; using System.Drawing; using System.Drawing.Drawing2D; using System.Drawing.Text; using System.Windows.Forms; using HotelPms.Share.Windows.Animations; using System; using System.Drawing.Imaging; namespace HotelPms.Share.Windows.Component { public class MaterialButton : Button { private float radius = 10F; /// /// 半径 /// public float Radius { get { return radius; } set { radius = value; Invalidate(); } } private readonly AnimationManager _animationManager; private bool m_Selected = false; private bool m_MouseFocused = false; private StringFormat m_StringFormat = new StringFormat(); //public event EventHandler ClickFinished; public new event EventHandler Click; public MaterialButton() { BackColor = Color.FromArgb(255, 0, 105, 217); ForeColor = Color.White; Cursor = Cursors.Hand; _animationManager = new AnimationManager(false) { Increment = 0.03, AnimationType = AnimationType.EaseOut }; _animationManager.OnAnimationProgress += sender => Invalidate(); _animationManager.OnAnimationFinished += _animationManager_OnAnimationFinished; FlatStyle = FlatStyle.Flat; //AutoSizeMode = AutoSizeMode.GrowAndShrink; //AutoSize = true; } private void _animationManager_OnAnimationFinished(object sender) { Click?.Invoke(this, new EventArgs()); //ClickFinished?.Invoke(this, new EventArgs()); } protected override void Dispose(bool disposing) { m_StringFormat.Dispose(); base.Dispose(disposing); } public override string Text { get { return base.Text; } set { base.Text = value; Invalidate(); } } protected override void OnEnter(EventArgs e) { base.OnEnter(e); m_Selected = true; } protected override void OnLeave(EventArgs e) { base.OnLeave(e); m_Selected = false; } protected override void OnMouseEnter(EventArgs e) { base.OnMouseEnter(e); m_MouseFocused = true; } protected override void OnMouseLeave(EventArgs e) { base.OnMouseLeave(e); m_MouseFocused = false; } protected override void OnMouseUp(MouseEventArgs mevent) { base.OnMouseUp(mevent); _animationManager.StartNewAnimation(AnimationDirection.In, mevent.Location); } protected override void OnPreviewKeyDown(PreviewKeyDownEventArgs e) { base.OnPreviewKeyDown(e); if (e.KeyCode == Keys.Enter) { _animationManager.StartNewAnimation(AnimationDirection.In, new Point(Width / 2, Height / 2)); } } protected override void OnPaint(PaintEventArgs pevent) { var g = pevent.Graphics; g.SmoothingMode = SmoothingMode.AntiAlias; g.Clear(Parent.BackColor); if (radius.CompareTo(0F) <= 0) { Color beginColor = m_MouseFocused ? (FlatAppearance.MouseOverBackColor == Color.Empty ? ControlPaint.Light(BackColor) : FlatAppearance.MouseOverBackColor) : m_Selected ? (FlatAppearance.MouseDownBackColor == Color.Empty ? ControlPaint.Light(BackColor) : FlatAppearance.MouseDownBackColor) : BackColor; using (SolidBrush backBrush = new SolidBrush(beginColor)) { g.FillRectangle(backBrush, ClientRectangle); } //線 if (this.FlatAppearance.BorderSize > 0 && !this.FlatAppearance.BorderColor.Equals(Color.Empty)) { using (Pen pen = new Pen(this.FlatAppearance.BorderColor, this.FlatAppearance.BorderSize)) { g.DrawRectangle(pen, ClientRectangle); } } } else { using (var backgroundPath = CreateRoundRect(ClientRectangle.X, ClientRectangle.Y, ClientRectangle.Width - 1, ClientRectangle.Height - 1, radius)) { Color beginColor = m_MouseFocused ? (FlatAppearance.MouseOverBackColor == Color.Empty ? ControlPaint.Light(BackColor) : FlatAppearance.MouseOverBackColor) : m_Selected ? (FlatAppearance.MouseDownBackColor == Color.Empty ? ControlPaint.LightLight(BackColor) : FlatAppearance.MouseDownBackColor) : BackColor; using (SolidBrush backBrush = new SolidBrush(beginColor)) { g.FillPath(backBrush, backgroundPath); } //線 if (this.FlatAppearance.BorderSize > 0 && !this.FlatAppearance.BorderColor.Equals(Color.Empty)) { using (Pen pen = new Pen(this.FlatAppearance.BorderColor, this.FlatAppearance.BorderSize)) { g.DrawPath(pen, backgroundPath); } } } } if (_animationManager.IsAnimating()) { for (int i = 0; i < _animationManager.GetAnimationCount(); i++) { var animationValue = _animationManager.GetProgress(i); var animationSource = _animationManager.GetSource(i); using (var rippleBrush = new SolidBrush(Color.FromArgb((int)(51 - (animationValue * 50)), Color.White))) { var rippleSize = (int)(animationValue * Width * 2); g.FillEllipse(rippleBrush, new Rectangle(animationSource.X - rippleSize / 2, animationSource.Y - rippleSize / 2, rippleSize, rippleSize)); } } } Rectangle textR = ClientRectangle; if (Image != null) { int x = 5; float rate = 0.5F; int width = (int)(ClientRectangle.Width * 0.3) - x; int height = (int)(ClientRectangle.Height * rate); //Zoom if ((double)Image.Width / (double)Image.Height > (double)width / (double)height) // image is wider { height = (int)((double)Image.Height / (double)Image.Width * (double)width); } else { width = (int)((double)Image.Width / (double)Image.Height * (double)height); } //居中 Rectangle imgRect = new Rectangle(x, (ClientRectangle.Height - height) / 2, width, height); ImageAttributes vAttr = new ImageAttributes(); vAttr.SetColorKey((Image as Bitmap).GetPixel(0, 0), (Image as Bitmap).GetPixel(0, 0)); pevent.Graphics.DrawImage(Image, imgRect, 0, 0, Image.Width, Image.Height, GraphicsUnit.Pixel, vAttr); textR = new Rectangle(new Point(x + ClientRectangle.X + width, ClientRectangle.Y), new Size(ClientRectangle.Width - width, ClientRectangle.Height)); } SetStringFormat(); using (SolidBrush foreBrush = new SolidBrush(this.ForeColor)) { g.DrawString(Text, Font, foreBrush, textR, m_StringFormat); } } public static GraphicsPath CreateRoundRect(float x, float y, float width, float height, float radius) { var gp = new GraphicsPath(); gp.AddLine(x + radius, y, x + width - (radius * 2), y); gp.AddArc(x + width - (radius * 2), y, radius * 2, radius * 2, 270, 90); gp.AddLine(x + width, y + radius, x + width, y + height - (radius * 2)); gp.AddArc(x + width - (radius * 2), y + height - (radius * 2), radius * 2, radius * 2, 0, 90); gp.AddLine(x + width - (radius * 2), y + height, x + radius, y + height); gp.AddArc(x, y + height - (radius * 2), radius * 2, radius * 2, 90, 90); gp.AddLine(x, y + height - (radius * 2), x, y + radius); gp.AddArc(x, y, radius * 2, radius * 2, 180, 90); gp.CloseFigure(); return gp; } public static GraphicsPath CreateRoundRect(Rectangle rect, float radius) { return CreateRoundRect(rect.X, rect.Y, rect.Width, rect.Height, radius); } private void SetStringFormat() { switch (this.TextAlign) { case ContentAlignment.BottomCenter: case ContentAlignment.BottomLeft: case ContentAlignment.BottomRight: m_StringFormat.LineAlignment = StringAlignment.Far; break; case ContentAlignment.MiddleCenter: case ContentAlignment.MiddleLeft: case ContentAlignment.MiddleRight: m_StringFormat.LineAlignment = StringAlignment.Center; break; case ContentAlignment.TopCenter: case ContentAlignment.TopLeft: case ContentAlignment.TopRight: m_StringFormat.LineAlignment = StringAlignment.Near; break; } switch (this.TextAlign) { case ContentAlignment.TopLeft: case ContentAlignment.BottomLeft: case ContentAlignment.MiddleLeft: m_StringFormat.Alignment = StringAlignment.Near; break; case ContentAlignment.MiddleCenter: case ContentAlignment.BottomCenter: case ContentAlignment.TopCenter: m_StringFormat.Alignment = StringAlignment.Center; break; case ContentAlignment.BottomRight: case ContentAlignment.MiddleRight: case ContentAlignment.TopRight: m_StringFormat.Alignment = StringAlignment.Far; break; } } } }