515 lines
15 KiB
C#
515 lines
15 KiB
C#
|
|
/*
|
|||
|
|
* 本代码受中华人民共和国著作权法保护,作者仅授权下载代码之人在学习和交流范围内
|
|||
|
|
* 自由使用与修改代码;欲将代码用于商业用途的,请与作者联系。
|
|||
|
|
* 使用本代码请保留此处信息。作者联系方式: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
|
|||
|
|
/// <summary>
|
|||
|
|
///
|
|||
|
|
/// </summary>
|
|||
|
|
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
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// 是否在这个按钮上按下了鼠标未释放
|
|||
|
|
/// </summary>
|
|||
|
|
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);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
/// <summary>
|
|||
|
|
/// 是否可见
|
|||
|
|
/// </summary>
|
|||
|
|
public bool Visible { get; set; }
|
|||
|
|
/// <summary>
|
|||
|
|
///
|
|||
|
|
/// </summary>
|
|||
|
|
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; }
|
|||
|
|
/// <summary>
|
|||
|
|
/// 画两次可以加深颜色
|
|||
|
|
/// </summary>
|
|||
|
|
public bool DrawForePathTwice { get; set; }
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// 用于在click事件中传回数据
|
|||
|
|
/// </summary>
|
|||
|
|
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; }
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// 获取或设置是否将绘制完全限制在指定的区域内
|
|||
|
|
/// </summary>
|
|||
|
|
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
|
|||
|
|
/// <summary>
|
|||
|
|
///
|
|||
|
|
/// </summary>
|
|||
|
|
/// <param name="e"></param>
|
|||
|
|
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
|
|||
|
|
/// <summary>
|
|||
|
|
///
|
|||
|
|
/// </summary>
|
|||
|
|
/// <param name="owner"></param>
|
|||
|
|
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
|
|||
|
|
}
|
|||
|
|
}
|