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;
|
|
/// <summary>
|
/// 半径
|
/// </summary>
|
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;
|
}
|
}
|
}
|
}
|