/*
* 本代码受中华人民共和国著作权法保护,作者仅授权下载代码之人在学习和交流范围内
* 自由使用与修改代码;欲将代码用于商业用途的,请与作者联系。
* 使用本代码请保留此处信息。作者联系方式:ping3108@163.com, 欢迎进行技术交流
*/
using System;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Windows.Forms;
using MGdu.WinFormUI.MyGraphics;
namespace MGdu.WinFormUI
{
//忽略没有注释警告
#pragma warning disable 1591
///
///
///
public class WLButton
{
#region private var
private Control _owner;
private GMButtonState _state;
private EventHandler _click;
private PaintEventHandler _paint;
private bool _capture;
private Rectangle _bounds;
#endregion
#region properties
///
/// 是否在这个按钮上按下了鼠标未释放
///
public bool Capture
{ get { return _capture; } }
public Size BtnSize
{
get { return Bounds.Size; }
}
public Point Location
{
get { return Bounds.Location; }
}
public ButtonForePathGetter ForePathGetter { get; set; }
public event EventHandler Click
{
add { _click = value; }
remove { _click = null; }
}
public event PaintEventHandler Paint
{
add { _paint = value; }
remove { _paint = null; }
}
public GMButtonState State
{
get { return _state; }
set
{
if (value != _state)
{
_state = value;
_owner.Invalidate(Bounds);
}
}
}
///
/// 是否可见
///
public bool Visible { get; set; }
///
///
///
public Rectangle Bounds
{
get { return _bounds; }
set
{
if (_bounds != value)
{
_bounds = value;
}
}
}
public Font ForeFont { get; set; }
public string Text { get; set; }
public Size ForePathSize { get; set; }
public ButtonColorTable ColorTable { get; set; }
public ButtonBorderType BorderType { get; set; }
public bool DrawLightGlass { get; set; }
///
/// 画两次可以加深颜色
///
public bool DrawForePathTwice { get; set; }
///
/// 用于在click事件中传回数据
///
public object ClickSendBackOject { get; set; }
public Image BackImageNormal { get; set; }
public Image BackImageHover { get; set; }
public Image BackImagePressed { get; set; }
public Image BackImageDisabled { get; set; }
public bool Enabled { get; set; }
public ForePathRatoteDirection RotateDirection { get; set; }
public ForePathRenderMode HowForePathRender { get; set; }
///
/// 获取或设置是否将绘制完全限制在指定的区域内
///
public bool RestrictedBounds { get; set; }
public int Radius { get; set; }
public RoundStyle RoundedType { get; set; }
#endregion
#region private render method
private void RenderNormal(Graphics g)
{
RenderInternal(g, BackImageNormal, ColorTable.BorderColorNormal,
ColorTable.BackColorNormal, ColorTable.ForeColorNormal);
}
private void RenderHover(Graphics g)
{
RenderInternal(g, BackImageHover, ColorTable.BorderColorHover,
ColorTable.BackColorHover, ColorTable.ForeColorHover);
}
private void RenderPressed(Graphics g)
{
RenderInternal(g, BackImagePressed, ColorTable.BorderColorPressed,
ColorTable.BackColorPressed, ColorTable.ForeColorPressed);
}
private void RenderDisabled(Graphics g)
{
RenderInternal(g, BackImageDisabled, ColorTable.BorderColorDisabled,
ColorTable.BackColorDisabled, ColorTable.ForeColorDisabled);
}
private void RenderInternal(Graphics g, Image backImage, Color borderColor,
Color backColor, Color foreColor)
{
Region oldClip = g.Clip;
Region newClip = null;
if (RestrictedBounds)
{
newClip = new Region(Bounds);
g.Clip = newClip;
}
if (backImage != null)
{
g.DrawImage(backImage, Bounds);
}
else
{
FillInBackground(g, backColor);
RenderForePathAndText(g, foreColor);
DrawBorder(g, borderColor);
}
if (RestrictedBounds)
{
g.Clip = oldClip;
newClip.Dispose();
}
}
private void FillInBackground(Graphics g, Color backColor)
{
BasicBlockPainter.RenderFlatBackground(
g,
Bounds,
backColor,
BorderType,
Radius,
RoundedType);
if (BorderType == ButtonBorderType.Ellipse && DrawLightGlass)
{
using (GraphicsPath gp = new GraphicsPath())
{
Rectangle rect = Bounds;
rect.Height--;
rect.Width--;
gp.AddEllipse(rect);
using (PathGradientBrush pb = new PathGradientBrush(gp))
{
pb.CenterPoint = new PointF(rect.X + rect.Width / 2.0f, rect.Y + rect.Height / 4.0f);
pb.CenterColor = Color.FromArgb(180, Color.White);
pb.SurroundColors = new Color[] { Color.FromArgb(40, Color.White) };
g.FillPath(pb, gp);
}
}
}
}
private void DrawBorder(Graphics g, Color borderColor)
{
BasicBlockPainter.RenderBorder(
g,
Bounds,
borderColor,
BorderType,
Radius,
RoundedType);
}
private void RenderForePathAndText(Graphics g, Color foreColor)
{
if (ForePathGetter != null)
{
if(string.IsNullOrEmpty(Text))
PathOnly(g,foreColor);
else
PathAndText(g,foreColor);
}
else if(!string.IsNullOrEmpty(Text))
TextOnly(g,foreColor);
}
private void PathOnly(Graphics g, Color foreColor)
{
using (GraphicsPath path = ForePathGetter(Bounds))
{
PathWithRotate(g, path, foreColor, Bounds);
if (DrawForePathTwice)
PathWithRotate(g, path, foreColor, Bounds);
}
}
private void TextOnly(Graphics g, Color foreColor)
{
Size size = TextRenderer.MeasureText(Text, ForeFont);
int x = Bounds.Left + (Bounds.Width - size.Width) / 2;
int y = Bounds.Top + (Bounds.Height - size.Height) / 2;
Rectangle textRect = new Rectangle(new Point(x, y), size);
TextRenderer.DrawText(
g,
Text,
ForeFont,
textRect,
foreColor,
TextFormatFlags.HorizontalCenter |
TextFormatFlags.VerticalCenter);
}
private void PathAndText(Graphics g, Color foreColor)
{
Size size = TextRenderer.MeasureText(Text, ForeFont);
Rectangle rect = Bounds;
rect.Offset(-size.Width / 2 + 2, 0);
using (GraphicsPath path = ForePathGetter(rect))
{
PathWithRotate(g, path, foreColor, rect);
int x = rect.Left + rect.Width / 2 + ForePathSize.Width / 2 + 1;
int y = rect.Top + (rect.Height - size.Height) / 2;
Rectangle textRect = new Rectangle(new Point(x, y), size);
TextRenderer.DrawText(
g,
Text,
ForeFont,
textRect,
foreColor,
TextFormatFlags.HorizontalCenter |
TextFormatFlags.VerticalCenter);
}
}
private void PathWithRotate(Graphics g, GraphicsPath path, Color foreColor, Rectangle pathRect)
{
Pen p = new Pen(foreColor);
SolidBrush sb = new SolidBrush(foreColor);
if (RotateDirection == ForePathRatoteDirection.Down)
{
if (HowForePathRender == ForePathRenderMode.Draw)
g.DrawPath(p, path);
else
g.FillPath(sb, path);
}
else
{
int dx = 0, dy = 0, angle = 0;
switch (RotateDirection)
{
case ForePathRatoteDirection.Left:
dx = ForePathSize.Width - 1;
dy = 0;
angle = 90;
break;
case ForePathRatoteDirection.Up:
dx = ForePathSize.Width - 1;
dy = ForePathSize.Height - 1;
angle = 180;
break;
case ForePathRatoteDirection.Right:
dx = 0;
dy = ForePathSize.Height - 1;
angle = 270;
break;
}
int pathX = pathRect.Left + (pathRect.Width - ForePathSize.Width) / 2;
int pathY = pathRect.Top + (pathRect.Height - ForePathSize.Height) / 2;
g.TranslateTransform(pathX, pathY);
g.TranslateTransform(dx, dy);
g.RotateTransform(angle);
using (GraphicsPath newPath = ForePathGetter(new Rectangle(Point.Empty, ForePathSize)))
{
if (HowForePathRender == ForePathRenderMode.Draw)
g.DrawPath(p, newPath);
else
g.FillPath(sb, newPath);
}
g.ResetTransform();
}
p.Dispose();
sb.Dispose();
}
#region mouse operation
private void MouseDown(Point location)
{
if (Bounds.Contains(location))
{
State = GMButtonState.Pressed;
_capture = true;
}
else
{
_capture = false;
}
}
private void MouseMove(Point location)
{
if (Bounds.Contains(location))
{
if (State == GMButtonState.Normal)
{
// 没有在窗体其他地方按下按钮
if (!_owner.Capture)
{
State = GMButtonState.Hover;
}
}
else if (State == GMButtonState.PressLeave)
{
State = GMButtonState.Pressed;
}
}
else
{
if (_capture)
{
State = GMButtonState.PressLeave;
}
else
{
State = GMButtonState.Normal;
}
}
}
private void MouseLeave(Point location)
{
State = GMButtonState.Normal;
_capture = false;
}
private void MouseUp(Point location)
{
if (Bounds.Contains(location))
{
State = GMButtonState.Hover;
if (_capture)
OnClick(EventArgs.Empty);
}
else
{
State = GMButtonState.Normal;
}
_capture = false;
}
#endregion
#endregion
#region event
///
///
///
///
protected virtual void OnClick(EventArgs e)
{
if (_click != null)
{
object obj = (ClickSendBackOject != null) ? ClickSendBackOject : this;
_click(obj, e);
}
}
protected virtual void OnPaint(PaintEventArgs e)
{
if (_paint != null)
{
_paint(this, e);
}
}
#endregion
#region public method
///
///
///
///
public WLButton(Control owner)
{
_owner = owner;
_state = GMButtonState.Normal;
Visible = true;
Enabled = true;
BorderType = ButtonBorderType.Rectangle;
DrawLightGlass = false;
RotateDirection = ForePathRatoteDirection.Down;
HowForePathRender = ForePathRenderMode.Draw;
RestrictedBounds = true;
Radius = 0;
RoundedType = RoundStyle.None;
}
public void DrawButton(Graphics g)
{
if (!Visible)
return;
if (Enabled)
{
switch (State)
{
case GMButtonState.Hover:
RenderHover(g);
break;
case GMButtonState.Pressed:
RenderPressed(g);
break;
default:
RenderNormal(g);
break;
}
}
else
{
RenderDisabled(g);
}
OnPaint(new PaintEventArgs(g, Bounds));
}
public void MouseOperation(Point location, MouseOperationType type)
{
if (!Visible)
return;
switch (type)
{
case MouseOperationType.Move:
MouseMove(location);
break;
case MouseOperationType.Down:
MouseDown(location);
break;
case MouseOperationType.Up:
MouseUp(location);
break;
case MouseOperationType.Leave:
MouseLeave(location);
break;
default:
break;
}
}
#endregion
}
}