RaUI/Source/ryControls/Controls/ButtonEX.cs
鑫Intel 6bc527a8a2 ### 2020-12-27 dev更新
------

#### ryControls    V2.1.2012.2701
- *.[改进]IconViewEx控件选中背景颜色支持渐变。
- *.[改进]支持设置IconViewEx控件选中字体颜色。
2020-12-27 17:03:04 +08:00

766 lines
27 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using ryControls.Skin;
using System;
using System.ComponentModel;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Windows.Forms;
namespace ryControls
{
/// <summary>
/// 控件的状态。
/// </summary>
public enum ControlState
{
/// <summary>
/// 正常
/// </summary>
Normal,
/// <summary>
/// 鼠标经过
/// </summary>
Hover,
/// <summary>
/// 鼠标按下
/// </summary>
Pressed,
}
/// <summary>
/// 鼠标的当前位置
/// </summary>
public enum ButtonMousePosition
{
/// <summary>
///
/// </summary>
None,
/// <summary>
///
/// </summary>
Button,
/// <summary>
///
/// </summary>
Splitebutton,
}
/// <summary>
/// 美化按钮
/// </summary>
public class ButtonEx : Button
{
private Color _baseColor = Color.FromArgb(12, 125, 182);//基颜色
private Color _foreColor = Color.White;//字体颜色
private ControlState _controlState;//控件状态
private int _imageWidth = 16;
private RoundStyle _roundStyle = RoundStyle.All;//圆角
private int _radius = 8; //圆角半径
/// <summary>
/// 普通按钮矩形位置
/// </summary>
internal Rectangle ButtonRect
{
get
{
if (ShowSpliteButton)
{
return new Rectangle(0, 0, ClientRectangle.Width - SpliteButtonWidth, ClientRectangle.Height);
}
else
{
return new Rectangle(0,0,Width,Height);
}
}
}
/// <summary>
///美化按钮
/// </summary>
public ButtonEx() : base()
{
ForeColor = Color.White;
this.SetStyle(
ControlStyles.UserPaint | //控件自行绘制,而不使用操作系统的绘制
ControlStyles.AllPaintingInWmPaint | //忽略擦出的消息,减少闪烁。
ControlStyles.OptimizedDoubleBuffer |//在缓冲区上绘制,不直接绘制到屏幕上,减少闪烁。
ControlStyles.ResizeRedraw | //控件大小发生变化时,重绘。
ControlStyles.SupportsTransparentBackColor, true);//支持透明背景颜色
}
private int _spliteButtonWidth = 18;
/// <summary>
/// 分割按钮的宽度
/// </summary>
[DefaultValue(18)]
[Description("分割按钮的宽度")]
public int SpliteButtonWidth
{
get { return _spliteButtonWidth; }
set
{
if (_spliteButtonWidth != value)
{
_spliteButtonWidth = value;
base.Invalidate();
}
}
}
private bool _showSpliteButton = false;
/// <summary>
/// 是否启用分割按钮
/// </summary>
[DefaultValue(false)]
[Description("是否启用分割按钮")]
public bool ShowSpliteButton
{
get { return _showSpliteButton; }
set
{
if (_showSpliteButton != value)
{
_showSpliteButton = value;
base.Invalidate();
}
}
}
private bool _UseDefSkin = true;
/// <summary>
///优先使用默认皮肤
/// </summary>
[Description("优先使用默认皮肤")]
[DefaultValue(typeof(bool), "true")]
public bool UseDefSkin
{
get
{
return _UseDefSkin;
}
set
{
_UseDefSkin = value;
base.Invalidate();
}
}
/// <summary>
///按钮基础背景色
/// </summary>
[Description("按钮基础背景色")]
[DefaultValue(typeof(Color), "12, 125, 182")]
public Color BaseColor
{
get
{
if(SkinCommon.UseDefSkin && UseDefSkin)
{
return SkinCommon.ButtonSkin.BackColor;
}
return _baseColor;
}
set
{
_baseColor = value;
base.Invalidate();
}
}
/// <summary>
///按钮字体颜色
/// </summary>
[Description("按钮字体颜色")]
[DefaultValue(typeof(Color), "255, 255, 255")]
public new Color ForeColor
{
get
{
if (SkinCommon.UseDefSkin && UseDefSkin)
{
return SkinCommon.ButtonSkin.ForeColor;
}
return _foreColor;
}
set
{
_foreColor = value;
base.Invalidate();
}
}
/// <summary>
///图片宽度,默认值为18px最小12px
/// </summary>
[Description("图片宽度,默认值为18px最小12px")]
[DefaultValue(16)]//默认值为18px最小12px
public int ImageWidth
{
get { return _imageWidth; }
set
{
if (value != _imageWidth)
{
_imageWidth = value < 12 ? 12 : value;
base.Invalidate();
}
}
}
/// <summary>
///圆角的位置,默认全部都是圆角
/// </summary>
[Description("圆角的位置,默认全部都是圆角")]
[DefaultValue(typeof(RoundStyle), "1")]//默认全部都是圆角
public RoundStyle RoundStyle
{
get { return _roundStyle; }
set
{
if (_roundStyle != value)
{
_roundStyle = value;
base.Invalidate();
}
}
}
/// <summary>
///设置圆角半径
/// </summary>
[Description("圆角半径")]
[DefaultValue(8)]//设置圆角半径默认值为8最小值为4px
public int Radius
{
get { return _radius; }
set
{
if (_radius != value)
{
_radius = value < 4 ? 4 : value;
base.Invalidate();
}
}
}
private bool _ColorGradient = false;
/// <summary>
/// 背景色是否渐变
/// </summary>
[DefaultValue(false)]
[Description("背景色是否渐变")]
public bool ColorGradient
{
get { return _ColorGradient; }
set
{
if (value != _ColorGradient)
{
_ColorGradient = value;
base.Invalidate();
}
}
}
private int _imageHeight = 16;
/// <summary>
/// 图片高度
/// </summary>
[DefaultValue(16)]
[Description("图片高度")]
public int ImageHeight
{
get { return _imageHeight; }
set
{
if (value != _imageHeight)
{
_imageHeight = value < 12 ? 12 : value;
base.Invalidate();
}
}
}
private int _imageTextSpace = 2;
/// <summary>
/// 图片与文字之间的间距
/// </summary>
[DefaultValue(2)]
[Description("图片与文字之间的间距")]
public int ImageTextSpace
{
get { return _imageTextSpace; }
set
{
if (_imageTextSpace != value)
{
_imageTextSpace = value < 0 ? 0 : value;
base.Invalidate();
}
}
}
private bool _pressOffset = true;
/// <summary>
/// 当鼠标按下时图片和文字是否产生偏移
/// </summary>
[DefaultValue(true)]
[Description("当鼠标按下时图片和文字是否产生偏移")]
public bool PressOffset
{
get { return _pressOffset; }
set
{
_pressOffset = value;
}
}
internal ControlState ControlState //控件的状态
{
get { return _controlState; }
set
{
if (_controlState != value)
{
_controlState = value;
base.Invalidate();
}
}
}
/// <summary>
/// 鼠标进入时
/// </summary>
/// <param name="e"></param>
protected override void OnMouseEnter(EventArgs e)//鼠标进入时
{
base.OnMouseEnter(e);
ControlState = ControlState.Hover;//正常
}
/// <summary>
/// 鼠标离开
/// </summary>
/// <param name="e"></param>
protected override void OnMouseLeave(EventArgs e)//鼠标离开
{
base.OnMouseLeave(e);
ControlState = ControlState.Normal;//正常
}
/// <summary>
/// 鼠标按下
/// </summary>
/// <param name="e"></param>
protected override void OnMouseDown(MouseEventArgs e)//鼠标按下
{
base.OnMouseDown(e);
if (e.Button == MouseButtons.Left && e.Clicks == 1)//鼠标左键且点击次数为1
{
ControlState = ControlState.Pressed;//按下的状态
}
}
/// <summary>
/// 鼠标弹起
/// </summary>
/// <param name="e"></param>
protected override void OnMouseUp(MouseEventArgs e)//鼠标弹起
{
base.OnMouseUp(e);
if (e.Button == MouseButtons.Left && e.Clicks == 1)
{
if (ClientRectangle.Contains(e.Location))//控件区域包含鼠标的位置
{
ControlState = ControlState.Hover;
}
else
{
ControlState = ControlState.Normal;
}
}
}
private ButtonMousePosition _mousePosition;
/// <summary>
/// 鼠标当前所在位置
/// </summary>
internal ButtonMousePosition CurrentMousePosition
{
get { return _mousePosition; }
set
{
if (_mousePosition != value)
{
_mousePosition = value;
base.Invalidate();
}
}
}
/// <summary>
/// 获取图像以及文字的位置
/// </summary>
/// <param name="imageRect"></param>
/// <param name="textRect"></param>
/// <param name="g"></param>
private void CalculateRect(
out Rectangle imageRect, out Rectangle textRect, Graphics g)
{
imageRect = Rectangle.Empty;
textRect = Rectangle.Empty;
SizeF textSize = g.MeasureString(Text, Font);
if (Image == null)
{
switch (TextAlign)
{
case ContentAlignment.BottomCenter:
textRect = new Rectangle((ButtonRect.Width - (int)textSize.Width) / 2, Height - (int)textSize.Height - 3, (int)textSize.Width, (int)textSize.Height);
break;
case ContentAlignment.BottomLeft:
textRect = new Rectangle(2, Height - (int)textSize.Height - 3, (int)textSize.Width, (int)textSize.Height);
break;
case ContentAlignment.BottomRight:
textRect = new Rectangle(ButtonRect.Width - (int)textSize.Width - 3, Height - (int)textSize.Height - 3, (int)textSize.Width, (int)textSize.Height);
break;
case ContentAlignment.MiddleCenter:
textRect = new Rectangle((ButtonRect.Width - (int)textSize.Width) / 2, (Height - (int)textSize.Height) / 2, (int)textSize.Width, (int)textSize.Height);
break;
case ContentAlignment.MiddleLeft:
textRect = new Rectangle(2, (Height - (int)textSize.Height) / 2, (int)textSize.Width, (int)textSize.Height);
break;
case ContentAlignment.MiddleRight:
textRect = new Rectangle(ButtonRect.Width - (int)textSize.Width - 3, (Height - (int)textSize.Height) / 2, (int)textSize.Width, (int)textSize.Height);
break;
case ContentAlignment.TopCenter:
textRect = new Rectangle((ButtonRect.Width - (int)textSize.Width) / 2, 2, (int)textSize.Width, (int)textSize.Height);
break;
case ContentAlignment.TopLeft:
textRect = new Rectangle(2, 2, (int)textSize.Width, (int)textSize.Height);
break;
case ContentAlignment.TopRight:
textRect = new Rectangle(ButtonRect.Width - (int)textSize.Width - 3, 2, (int)textSize.Width, (int)textSize.Height);
break;
}
if (PressOffset && ControlState == ControlState.Pressed && CurrentMousePosition == ButtonMousePosition.Button)
{
textRect.X += 1;
textRect.Y += 1;
}
if (RightToLeft == RightToLeft.Yes)
{
textRect.X = ButtonRect.Width - textRect.Right;
}
return;
}
if (this.Text == "")
{
switch (ImageAlign)
{
case ContentAlignment.BottomCenter:
imageRect = new Rectangle((ButtonRect.Width - ImageWidth) / 2, Height - ImageHeight - 3, ImageWidth, ImageHeight);
break;
case ContentAlignment.BottomLeft:
imageRect = new Rectangle(2, Height - ImageHeight - 3, ImageWidth, ImageHeight);
break;
case ContentAlignment.BottomRight:
imageRect = new Rectangle(ButtonRect.Width - ImageWidth - 3, Height - ImageHeight - 3, ImageWidth, ImageHeight);
break;
case ContentAlignment.MiddleCenter:
imageRect = new Rectangle((ButtonRect.Width - ImageWidth) / 2, (Height - ImageHeight) / 2, ImageWidth, ImageHeight);
break;
case ContentAlignment.MiddleLeft:
imageRect = new Rectangle(2, (Height - ImageHeight) / 2, ImageWidth, ImageHeight);
break;
case ContentAlignment.MiddleRight:
imageRect = new Rectangle(ButtonRect.Width - ImageWidth - 3, (Height - ImageHeight) / 2, ImageWidth, ImageHeight);
break;
case ContentAlignment.TopCenter:
imageRect = new Rectangle((ButtonRect.Width - ImageWidth) / 2, 2, ImageWidth, ImageHeight);
break;
case ContentAlignment.TopLeft:
imageRect = new Rectangle(2, 2, ImageWidth, ImageHeight);
break;
case ContentAlignment.TopRight:
imageRect = new Rectangle(ButtonRect.Width - ImageWidth - 3, 2, ImageWidth, ImageHeight);
break;
}
if (PressOffset && ControlState == ControlState.Pressed && CurrentMousePosition == ButtonMousePosition.Button)
{
imageRect.X += 1;
imageRect.Y += 1;
}
if (RightToLeft == RightToLeft.Yes)
{
imageRect.X = ButtonRect.Width - imageRect.Right;
}
return;
}
switch (TextImageRelation)
{
case TextImageRelation.Overlay:
imageRect = new Rectangle(
(ButtonRect.Width - ImageWidth - (int)textSize.Width - ImageTextSpace) / 2,
(Height - ImageHeight) / 2,
ImageWidth,
ImageHeight);
textRect = new Rectangle(
imageRect.Right + ImageTextSpace,
(Height - (int)textSize.Height) / 2,
(int)textSize.Width,
(int)textSize.Height);
break;
case TextImageRelation.ImageAboveText:
imageRect = new Rectangle(
(ButtonRect.Width - ImageWidth) / 2,
(Height - ImageHeight - (int)textSize.Height - ImageTextSpace) / 2,
ImageWidth,
ImageHeight);
textRect = new Rectangle(
(ButtonRect.Width - (int)textSize.Width) / 2,
imageRect.Bottom + ImageTextSpace,
(int)textSize.Width,
(int)textSize.Height);
break;
case TextImageRelation.ImageBeforeText:
imageRect = new Rectangle(
(ButtonRect.Width - ImageWidth - (int)textSize.Width - ImageTextSpace) / 2,
(Height - ImageHeight) / 2,
ImageWidth,
ImageHeight);
textRect = new Rectangle(
imageRect.Right + ImageTextSpace,
(Height - (int)textSize.Height) / 2,
(int)textSize.Width,
(int)textSize.Height);
break;
case TextImageRelation.TextAboveImage:
textRect = new Rectangle(
(ButtonRect.Width - (int)textSize.Width) / 2,
(Height - (int)textSize.Height - ImageHeight - ImageTextSpace) / 2,
(int)textSize.Width,
(int)textSize.Height);
imageRect = new Rectangle(
(ButtonRect.Width - ImageWidth) / 2,
textRect.Bottom + ImageTextSpace,
ImageWidth,
ImageHeight);
break;
case TextImageRelation.TextBeforeImage:
textRect = new Rectangle(
(ButtonRect.Width - ImageWidth - (int)textSize.Width - ImageTextSpace) / 2,
(Height - (int)textSize.Height) / 2,
(int)textSize.Width,
(int)textSize.Height);
imageRect = new Rectangle(
textRect.Right + ImageTextSpace,
(Height - ImageHeight) / 2,
ImageWidth,
ImageHeight);
break;
}
if (PressOffset && ControlState == ControlState.Pressed && CurrentMousePosition == ButtonMousePosition.Button)
{
imageRect.X += 1;
imageRect.Y += 1;
textRect.X += 1;
textRect.Y += 1;
}
if (RightToLeft == RightToLeft.Yes)
{
imageRect.X = ButtonRect.Width - imageRect.Right;
textRect.X = ButtonRect.Width - textRect.Right;
}
}
/// <summary>
///
/// </summary>
/// <param name="e"></param>
protected override void OnPaint(PaintEventArgs e)
{
base.OnPaint(e);
base.OnPaintBackground(e);
Graphics g = e.Graphics;
//Rectangle imageRect;//图像区域
//Rectangle textRect;//文字区域
this.CalculateRect(out Rectangle imageRect, out Rectangle textRect, g);
g.SmoothingMode = SmoothingMode.AntiAlias;
Color baseColor;
Color borderColor;
Color innerBorderColor = this.BaseColor;//Color.FromArgb(200, 255, 255, 255); ;
if (Enabled)
{
switch (ControlState)
{
case ControlState.Hover:
baseColor = GetColor(BaseColor, 0, -35, -24, -30);
borderColor = BaseColor;
break;
case ControlState.Pressed:
baseColor = GetColor(BaseColor, 0, -35, -24, -9);
borderColor = BaseColor;
break;
default:
baseColor = BaseColor;
borderColor = BaseColor;
break;
}
}
else
{
baseColor = SystemColors.ControlDark;
borderColor = SystemColors.ControlDark;
}
this.RenderBackgroundInternal(
g,
ClientRectangle,
baseColor,
borderColor,
innerBorderColor,
RoundStyle,
Radius,
0.35f,
false,
true,
LinearGradientMode.Vertical);
if (Image != null)
{
g.InterpolationMode = InterpolationMode.HighQualityBilinear;
g.DrawImage(Image, imageRect, 0, 0, Image.Width, Image.Height, GraphicsUnit.Pixel);
}
TextRenderer.DrawText(g, Text, Font, textRect, ForeColor, GetTextFormatFlags(TextAlign, RightToLeft == RightToLeft.Yes));
}
private Color GetColor(Color colorBase, int a, int r, int g, int b)
{
int a0 = colorBase.A;
int r0 = colorBase.R;
int g0 = colorBase.G;
int b0 = colorBase.B;
if (a + a0 > 255) { a = 255; } else { a = Math.Max(a + a0, 0); }
if (r + r0 > 255) { r = 255; } else { r = Math.Max(r + r0, 0); }
if (g + g0 > 255) { g = 255; } else { g = Math.Max(g + g0, 0); }
if (b + b0 > 255) { b = 255; } else { b = Math.Max(b + b0, 0); }
return Color.FromArgb(a, r, g, b);
}
internal void RenderBackgroundInternal(
Graphics g,
Rectangle rect,
Color baseColor,
Color borderColor,
Color innerBorderColor,
RoundStyle style,
int roundWidth,//圆角半径
float basePosition,
bool drawBorder,
bool drawGlass,
LinearGradientMode mode)
{
if (drawBorder)//是否画边框
{
rect.Width--;
rect.Height--;
}
using (LinearGradientBrush brush = new LinearGradientBrush(rect, Color.Transparent, Color.Transparent, mode))
{
Color[] colors = new Color[4];
if (ColorGradient)
{
colors[0] = GetColor(baseColor, 0, 35, 24, 9);
colors[1] = GetColor(baseColor, 0, 0, 0, 0);
colors[2] = baseColor;
colors[3] = GetColor(baseColor, 0, 0, 0, 0);
}
else
{
colors[0] = baseColor;
colors[1] = baseColor;
colors[2] = baseColor;
colors[3] = baseColor;
}
ColorBlend blend = new ColorBlend()
{
Positions = new float[] { 0.0f, basePosition, basePosition, 1.0f },
Colors = colors
};
brush.InterpolationColors = blend;
if (style != RoundStyle.None)
{
using (GraphicsPath path =
Drawing.CreatePath(rect, roundWidth, style, false))
{
g.FillPath(brush, path);
}
if (baseColor.A > 80)
{
Rectangle rectTop = rect;
if (mode == LinearGradientMode.Vertical)
{
// rectTop.Height = (int)(rectTop.Height * basePosition);
}
else
{
// rectTop.Width = (int)(rect.Width * basePosition);
}
using (GraphicsPath pathTop = Drawing.CreatePath(
rectTop, roundWidth, style, false))
{
if (ColorGradient)
{
using (SolidBrush brushAlpha =
new SolidBrush(Color.FromArgb(80, 255, 255, 255)))
{
g.FillPath(brushAlpha, pathTop);
}
}
}
}
}
}
}
internal static TextFormatFlags GetTextFormatFlags(
ContentAlignment alignment,
bool rightToleft)
{
TextFormatFlags flags = TextFormatFlags.WordBreak |
TextFormatFlags.SingleLine;
if (rightToleft)
{
flags |= TextFormatFlags.RightToLeft | TextFormatFlags.Right;
}
switch (alignment)
{
case ContentAlignment.BottomCenter:
flags |= TextFormatFlags.Bottom | TextFormatFlags.HorizontalCenter;
break;
case ContentAlignment.BottomLeft:
flags |= TextFormatFlags.Bottom | TextFormatFlags.Left;
break;
case ContentAlignment.BottomRight:
flags |= TextFormatFlags.Bottom | TextFormatFlags.Right;
break;
case ContentAlignment.MiddleCenter:
flags |= TextFormatFlags.HorizontalCenter |
TextFormatFlags.VerticalCenter;
break;
case ContentAlignment.MiddleLeft:
flags |= TextFormatFlags.VerticalCenter | TextFormatFlags.Left;
break;
case ContentAlignment.MiddleRight:
flags |= TextFormatFlags.VerticalCenter | TextFormatFlags.Right;
break;
case ContentAlignment.TopCenter:
flags |= TextFormatFlags.Top | TextFormatFlags.HorizontalCenter;
break;
case ContentAlignment.TopLeft:
flags |= TextFormatFlags.Top | TextFormatFlags.Left;
break;
case ContentAlignment.TopRight:
flags |= TextFormatFlags.Top | TextFormatFlags.Right;
break;
}
return flags;
}
}
}