// 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.Drawing2D; using System.Windows.Forms; namespace AntdUI { [ToolboxItem(false)] public class IControl : Control, BadgeConfig { public IControl() { SetStyle( ControlStyles.AllPaintingInWmPaint | ControlStyles.OptimizedDoubleBuffer | ControlStyles.ResizeRedraw | ControlStyles.DoubleBuffer | ControlStyles.SupportsTransparentBackColor | ControlStyles.ContainerControl | ControlStyles.UserPaint, true); UpdateStyles(); } #region 属性 #region 徽标 string? badge = null; [Description("徽标内容"), Category("徽标"), DefaultValue(null)] public string? Badge { get => badge; set { if (badge == value) return; badge = value; Invalidate(); } } float badgeSize = .6F; [Description("徽标比例"), Category("徽标"), DefaultValue(.6F)] public float BadgeSize { get => badgeSize; set { if (badgeSize != value) { badgeSize = value; if (badge != null) Invalidate(); } } } bool badgeMode = false; [Description("徽标模式(镂空)"), Category("徽标"), DefaultValue(false)] public bool BadgeMode { get => badgeMode; set { if (badgeMode != value) { badgeMode = value; if (badge != null) Invalidate(); } } } Color? badgeback = null; [Description("徽标背景颜色"), Category("徽标"), DefaultValue(null)] public Color? BadgeBack { get => badgeback; set { if (badgeback != value) { badgeback = value; if (badge != null) Invalidate(); } } } /// /// 徽标偏移X /// [Description("徽标偏移X"), Category("徽标"), DefaultValue(1)] public int BadgeOffsetX { get; set; } = 1; /// /// 徽标偏移Y /// [Description("徽标偏移Y"), Category("徽标"), DefaultValue(1)] public int BadgeOffsetY { get; set; } = 1; #endregion #endregion /// /// Spin 加载中 /// /// 需要等待的委托 /// 运行结束后的回调 public void Spin(Action action, Action? end = null) { Spin(new Spin.Config(), action, end); } /// /// Spin 加载中 /// /// 加载文本 /// 需要等待的委托 /// 运行结束后的回调 public void Spin(string text, Action action, Action? end = null) { Spin(new Spin.Config { Text = text }, action, end); } /// /// Spin 加载中 /// /// 自定义配置 /// 需要等待的委托 /// 运行结束后的回调 public void Spin(Spin.Config config, Action action, Action? end = null) { AntdUI.Spin.open(this, config, action, end); } #region 帮助类 [Browsable(false)] public virtual GraphicsPath RenderRegion { get { var path = new GraphicsPath(); path.AddRectangle(ClientRectangle); return path; } } /// /// 真实区域 /// [Browsable(false)] public virtual Rectangle ReadRectangle { get => ClientRectangle.PaddingRect(Padding); } internal void IOnSizeChanged() { if (InvokeRequired) { Invoke(new Action(() => { IOnSizeChanged(); })); return; } OnSizeChanged(EventArgs.Empty); } #region 鼠标 CursorType oldcursor = CursorType.Default; public void SetCursor(bool val) => SetCursor(val ? CursorType.Hand : CursorType.Default); public void SetCursor(CursorType cursor = CursorType.Default) { if (oldcursor == cursor) return; oldcursor = cursor; if (InvokeRequired) { Invoke(new Action(() => { SetCursor(cursor); })); return; } switch (cursor) { case CursorType.Hand: Cursor = HandCursor; break; case CursorType.No: Cursor = Cursors.No; break; case CursorType.SizeAll: Cursor = Cursors.SizeAll; break; case CursorType.VSplit: Cursor = Cursors.VSplit; break; case CursorType.Default: default: Cursor = DefaultCursor; break; } } [Description("悬停光标"), Category("光标"), DefaultValue(typeof(Cursor), "Hand")] public virtual Cursor HandCursor { get; set; } = Cursors.Hand; #endregion #region 渲染文本 internal void PaintText(Graphics g, string? text, Rectangle path, StringFormat stringFormat, bool enabled) { using (var brush = new SolidBrush(enabled ? ForeColor : Style.Db.TextQuaternary)) { g.DrawStr(text, Font, brush, path, stringFormat); } } internal void PaintText(Graphics g, string? text, RectangleF path, StringFormat stringFormat, bool enabled) { using (var brush = new SolidBrush(enabled ? ForeColor : Style.Db.TextQuaternary)) { g.DrawStr(text, Font, brush, path, stringFormat); } } #endregion #endregion #region 触屏 bool mdown = false; int mdownd = 0, oldX, oldY; protected virtual void OnTouchDown(int x, int y) { oldMY = 0; oldX = x; oldY = y; if (Config.TouchEnabled) { taskTouch?.Dispose(); taskTouch = null; mdownd = 0; mdown = true; } } int oldMY = 0; protected virtual bool OnTouchMove(int x, int y) { if (mdown) { int moveX = oldX - x, moveY = oldY - y, moveXa = Math.Abs(moveX), moveYa = Math.Abs(moveY); oldMY = moveY; if (mdownd > 0) { if (mdownd == 1) OnTouchScrollY(-moveY); else OnTouchScrollX(-moveX); oldX = x; oldY = y; return false; } else if (moveXa > 2 || moveYa > 2) { if (moveYa > moveXa) { mdownd = 1; OnTouchScrollY(-moveY); } else { mdownd = 2; OnTouchScrollX(-moveX); } oldX = x; oldY = y; return false; } } return true; } ITask? taskTouch = null; protected virtual bool OnTouchUp() { taskTouch?.Dispose(); taskTouch = null; mdown = false; if (mdownd > 0) { if (mdownd == 1) { int moveY = oldMY, moveYa = Math.Abs(moveY); if (moveYa > 10) { // 缓冲动画 int duration = (int)Math.Ceiling(moveYa * .1F), incremental = moveYa / 2, sleep = 20; if (moveY > 0) { taskTouch = new ITask(this, () => { if (moveYa > 0 && OnTouchScrollY(-incremental)) { moveYa -= duration; return true; } return false; }, sleep); } else { taskTouch = new ITask(this, () => { if (moveYa > 0 && OnTouchScrollY(incremental)) { moveYa -= duration; return true; } return false; }, sleep); } } } return false; } return true; } protected void OnTouchCancel() { taskTouch?.Dispose(); taskTouch = null; mdown = false; } protected virtual bool OnTouchScrollX(int value) => false; protected virtual bool OnTouchScrollY(int value) => false; protected override void OnMouseWheel(MouseEventArgs e) { taskTouch?.Dispose(); taskTouch = null; base.OnMouseWheel(e); } #endregion } public enum CursorType { Default, Hand, IBeam, No, SizeAll, VSplit, } public interface BadgeConfig { /// /// 徽标内容 /// string? Badge { get; set; } /// /// 徽标大小 /// float BadgeSize { get; set; } /// /// 徽标背景颜色 /// Color? BadgeBack { get; set; } } public interface ShadowConfig { /// /// 阴影大小 /// int Shadow { get; set; } /// /// 阴影颜色 /// Color? ShadowColor { get; set; } /// /// 阴影透明度 /// float ShadowOpacity { get; set; } /// /// 阴影偏移X /// int ShadowOffsetX { get; set; } /// /// 阴影偏移Y /// int ShadowOffsetY { get; set; } } }