// COPYRIGHT (C) Tom. ALL RIGHTS RESERVED.
// THE AntdUI PROJECT IS AN WINFORM LIBRARY LICENSED UNDER THE Apache-2.0 License.
// LICENSED UNDER THE Apache License, VERSION 2.0 (THE "License")
// YOU MAY NOT USE THIS FILE EXCEPT IN COMPLIANCE WITH THE License.
// YOU MAY OBTAIN A COPY OF THE LICENSE AT
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING, SOFTWARE
// DISTRIBUTED UNDER THE LICENSE IS DISTRIBUTED ON AN "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
// SEE THE LICENSE FOR THE SPECIFIC LANGUAGE GOVERNING PERMISSIONS AND
// LIMITATIONS UNDER THE License.
// GITEE: https://gitee.com/antdui/AntdUI
// GITHUB: https://github.com/AntdUI/AntdUI
// CSDN: https://blog.csdn.net/v_132
// QQ: 17379620
using System;
using System.ComponentModel;
using System.Drawing;
using System.Drawing.Design;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;
using System.Windows.Forms;
namespace AntdUI
{
///
/// Panel 面板
///
/// 内容区域。
[Description("Panel 面板")]
[ToolboxItem(true)]
[DefaultProperty("Text")]
[Designer(typeof(IControlDesigner))]
public class Panel : IControl, ShadowConfig, IMessageFilter, IEventListener
{
#region 属性
int radius = 6;
///
/// 圆角
///
[Description("圆角"), Category("外观"), DefaultValue(6)]
public int Radius
{
get => radius;
set
{
if (radius == value) return;
radius = value;
Invalidate();
}
}
#region 阴影
Padding _padding = new Padding(0);
[Description("内边距"), Category("外观"), DefaultValue(typeof(Padding), "0, 0, 0, 0")]
public Padding padding
{
get => _padding;
set
{
if (_padding == value) return;
_padding = value;
shadow_temp?.Dispose();
shadow_temp = null;
OnSizeChanged(EventArgs.Empty);
}
}
int shadow = 0;
///
/// 阴影大小
///
[Description("阴影"), Category("外观"), DefaultValue(0)]
public int Shadow
{
get => shadow;
set
{
if (shadow == value) return;
shadow = value;
shadow_temp?.Dispose();
shadow_temp = null;
OnSizeChanged(EventArgs.Empty);
}
}
Color? shadowColor;
///
/// 阴影颜色
///
[Description("阴影颜色"), Category("阴影"), DefaultValue(null)]
[Editor(typeof(Design.ColorEditor), typeof(UITypeEditor))]
public Color? ShadowColor
{
get => shadowColor;
set
{
if (shadowColor == value) return;
shadowColor = value;
shadow_temp?.Dispose();
shadow_temp = null;
Invalidate();
}
}
int shadowOffsetX = 0;
///
/// 阴影偏移X
///
[Description("阴影偏移X"), Category("阴影"), DefaultValue(0)]
public int ShadowOffsetX
{
get => shadowOffsetX;
set
{
if (shadowOffsetX == value) return;
shadowOffsetX = value;
shadow_temp?.Dispose();
shadow_temp = null;
OnSizeChanged(EventArgs.Empty);
}
}
int shadowOffsetY = 0;
///
/// 阴影偏移Y
///
[Description("阴影偏移Y"), Category("阴影"), DefaultValue(0)]
public int ShadowOffsetY
{
get => shadowOffsetY;
set
{
if (shadowOffsetY == value) return;
shadowOffsetY = value;
shadow_temp?.Dispose();
shadow_temp = null;
OnSizeChanged(EventArgs.Empty);
}
}
float shadowOpacity = 0.1F;
///
/// 阴影透明度
///
[Description("阴影透明度"), Category("阴影"), DefaultValue(0.1F)]
public float ShadowOpacity
{
get => shadowOpacity;
set
{
if (shadowOpacity == value) return;
if (value < 0) value = 0;
else if (value > 1) value = 1;
shadowOpacity = value;
AnimationHoverValue = shadowOpacity;
Invalidate();
}
}
///
/// 阴影透明度动画使能
///
[Description("阴影透明度动画使能"), Category("阴影"), DefaultValue(false)]
public bool ShadowOpacityAnimation { get; set; }
float shadowOpacityHover = 0.3F;
///
/// 悬停阴影后透明度
///
[Description("悬停阴影后透明度"), Category("阴影"), DefaultValue(0.3F)]
public float ShadowOpacityHover
{
get => shadowOpacityHover;
set
{
if (shadowOpacityHover == value) return;
if (value < 0) value = 0;
else if (value > 1) value = 1;
shadowOpacityHover = value;
Invalidate();
}
}
TAlignMini shadowAlign = TAlignMini.None;
[Description("阴影方向"), Category("阴影"), DefaultValue(TAlignMini.None)]
public TAlignMini ShadowAlign
{
get => shadowAlign;
set
{
if (shadowAlign == value) return;
shadowAlign = value;
shadow_temp?.Dispose();
shadow_temp = null;
OnSizeChanged(EventArgs.Empty);
}
}
#endregion
#region 背景
Color? back;
///
/// 背景颜色
///
[Description("背景颜色"), Category("外观"), DefaultValue(null)]
[Editor(typeof(Design.ColorEditor), typeof(UITypeEditor))]
public Color? Back
{
get => back;
set
{
if (back == value) return;
back = value;
Invalidate();
}
}
Image? backImage = null;
///
/// 背景图片
///
[Description("背景图片"), Category("外观"), DefaultValue(null)]
public new Image? BackgroundImage
{
get => backImage;
set
{
if (backImage == value) return;
backImage = value;
Invalidate();
}
}
TFit backFit = TFit.Fill;
///
/// 背景图片布局
///
[Description("背景图片布局"), Category("外观"), DefaultValue(TFit.Fill)]
public new TFit BackgroundImageLayout
{
get => backFit;
set
{
if (backFit == value) return;
backFit = value;
Invalidate();
}
}
#endregion
#region 箭头
int arrwoSize = 8;
///
/// 箭头大小
///
[Description("箭头大小"), Category("箭头"), DefaultValue(8)]
public int ArrowSize
{
get => arrwoSize;
set
{
if (arrwoSize == value) return;
arrwoSize = value;
Invalidate();
}
}
TAlign arrowAlign = TAlign.None;
///
/// 箭头方向
///
[Description("箭头方向"), Category("箭头"), DefaultValue(TAlign.None)]
public TAlign ArrowAlign
{
get => arrowAlign;
set
{
if (arrowAlign == value) return;
arrowAlign = value;
Invalidate();
}
}
#endregion
#region 边框
float borderWidth = 0F;
///
/// 边框宽度
///
[Description("边框宽度"), Category("边框"), DefaultValue(0F)]
public float BorderWidth
{
get => borderWidth;
set
{
if (borderWidth == value) return;
borderWidth = value;
OnSizeChanged(EventArgs.Empty);
}
}
Color? borderColor;
///
/// 边框颜色
///
[Description("边框颜色"), Category("边框"), DefaultValue(null)]
[Editor(typeof(Design.ColorEditor), typeof(UITypeEditor))]
public Color? BorderColor
{
get => borderColor;
set
{
if (borderColor == value) return;
borderColor = value;
Invalidate();
}
}
#endregion
#endregion
public override Rectangle DisplayRectangle
{
get => ClientRectangle.DeflateRect(Padding, this, shadowAlign, borderWidth);
}
#region 渲染
protected override void OnPaint(PaintEventArgs e)
{
var rect = ClientRectangle;
if (rect.Width > 0 && rect.Height > 0)
{
var g = e.Graphics.High();
var rect_read = ReadRectangle;
float _radius = radius * Config.Dpi;
using (var brush = new SolidBrush(back ?? Style.Db.BgContainer))
{
using (var path = DrawShadow(g, _radius, rect, rect_read))
{
g.FillPath(brush, path);
if (backImage != null) g.PaintImg(rect_read, backImage, backFit, _radius, false);
if (borderWidth > 0)
{
using (var brush_bor = new Pen(borderColor ?? Style.Db.BorderColor, borderWidth * Config.Dpi))
{
g.DrawPath(brush_bor, path);
}
}
}
if (ArrowAlign != TAlign.None) g.FillPolygon(brush, ArrowAlign.AlignLines(ArrowSize, rect, rect_read));
}
this.PaintBadge(g);
}
base.OnPaint(e);
}
Bitmap? shadow_temp = null;
///
/// 绘制阴影
///
/// GDI
/// 客户区域
/// 真实区域
GraphicsPath DrawShadow(Graphics g, float radius, Rectangle rect_client, Rectangle rect_read)
{
var path = rect_read.RoundPath(radius, shadowAlign);
if (shadow > 0)
{
int shadow = (int)(Shadow * Config.Dpi), shadowOffsetX = (int)(ShadowOffsetX * Config.Dpi), shadowOffsetY = (int)(ShadowOffsetY * Config.Dpi);
if (shadow_temp == null || (shadow_temp.Width != rect_client.Width || shadow_temp.Height != rect_client.Height))
{
shadow_temp?.Dispose();
shadow_temp = path.PaintShadow(rect_client.Width, rect_client.Height, shadowColor ?? Style.Db.TextBase, shadow);
}
using (var attributes = new ImageAttributes())
{
var matrix = new ColorMatrix();
if (AnimationHover) matrix.Matrix33 = AnimationHoverValue;
else if (ExtraMouseHover) matrix.Matrix33 = shadowOpacityHover;
else matrix.Matrix33 = shadowOpacity;
attributes.SetColorMatrix(matrix, ColorMatrixFlag.Default, ColorAdjustType.Bitmap);
g.DrawImage(shadow_temp, new Rectangle(rect_client.X + shadowOffsetX, rect_client.Y + shadowOffsetY, rect_client.Width, rect_client.Height), 0, 0, shadow_temp.Width, shadow_temp.Height, GraphicsUnit.Pixel, attributes);
}
}
return path;
}
public override Rectangle ReadRectangle
{
get => ClientRectangle.DeflateRect(_padding).PaddingRect(this, shadowAlign, borderWidth);
}
public override GraphicsPath RenderRegion
{
get => ReadRectangle.RoundPath(radius * Config.Dpi);
}
#endregion
#region 鼠标
float AnimationHoverValue = 0.1F;
bool AnimationHover = false;
bool _mouseHover = false;
bool ExtraMouseHover
{
get => _mouseHover;
set
{
if (_mouseHover == value) return;
_mouseHover = value;
if (Enabled && ShadowOpacityAnimation && shadow > 0 && shadowOpacityHover > 0 && shadowOpacityHover > shadowOpacity)
{
if (Config.Animation)
{
ThreadHover?.Dispose();
AnimationHover = true;
float addvalue = shadowOpacityHover / 12F;
if (value)
{
ThreadHover = new ITask(this, () =>
{
AnimationHoverValue = AnimationHoverValue.Calculate(addvalue);
if (AnimationHoverValue >= shadowOpacityHover) { AnimationHoverValue = shadowOpacityHover; return false; }
Invalidate();
return true;
}, 20, () =>
{
AnimationHover = false;
Invalidate();
});
}
else
{
ThreadHover = new ITask(this, () =>
{
AnimationHoverValue = AnimationHoverValue.Calculate(-addvalue);
if (AnimationHoverValue <= shadowOpacity) { AnimationHoverValue = shadowOpacity; return false; }
Invalidate();
return true;
}, 20, () =>
{
AnimationHover = false;
Invalidate();
});
}
}
else Invalidate();
}
}
}
public void SetMouseHover(bool val) { ExtraMouseHover = val; }
#region 动画
protected override void Dispose(bool disposing)
{
ThreadHover?.Dispose();
Application.RemoveMessageFilter(this);
shadow_temp?.Dispose();
shadow_temp = null;
base.Dispose(disposing);
}
ITask? ThreadHover = null;
#endregion
protected override void OnMouseEnter(EventArgs e)
{
base.OnMouseEnter(e);
ExtraMouseHover = true;
}
#region 离开监控
public bool PreFilterMessage(ref System.Windows.Forms.Message m)
{
if (m.Msg == 0x2a1 || m.Msg == 0x2a3)
{
ExtraMouseHover = ClientRectangle.Contains(PointToClient(MousePosition));
return false;
}
return false;
}
#endregion
protected override void OnLeave(EventArgs e)
{
base.OnLeave(e);
ExtraMouseHover = false;
}
#endregion
protected override void OnHandleCreated(EventArgs e)
{
base.OnHandleCreated(e);
Application.AddMessageFilter(this);
this.AddListener();
}
#region 主题变化
public void HandleEvent(EventType id, object? tag)
{
switch (id)
{
case EventType.THEME:
shadow_temp?.Dispose();
shadow_temp = null;
break;
}
}
#endregion
}
internal class IControlDesigner : System.Windows.Forms.Design.ParentControlDesigner
{
}
}