/*************************************************** * CircleButton 2.0 · Red badge with built-in number * Author : Gong Yuchao (2017-08-16), rev 2025-07-17 ***************************************************/ using Lskj.Business; using System; using System.ComponentModel; using System.Diagnostics; using System.Drawing; using System.Drawing.Drawing2D; using System.Windows.Forms; namespace Lskj.Control { [DefaultEvent(nameof(Click))] public partial class CircleButton : Button { /* ───────── 可调属性 ───────── */ private int _radius = 18 / 2; // 直径 18px [Category("布局"), Description("圆点半径(px)")] public int Radius { get => _radius; set { _radius = Math.Max(4, value); SyncSize(); } } private int _number; [Category("数据"), Description("角标数字(>99 显示 99)")] public int Number { get => _number; set { _number = Math.Max(0, value); Invalidate(); } } [Category("外观"), Description("普通状态图(可省略)")] public Image ImageNormal { get => _imgNormal; set { _imgNormal = value; if (!_hover) BackgroundImage = value; } } private Image _imgNormal; [Category("外观"), Description("悬停状态图(可省略)")] public Image ImageHover { get; set; } [Category("外观"), Description("边框颜色(透明=无)")] public Color BorderColor { get; set; } = Color.Transparent; [Category("外观"), Description("边框粗细(px)")] public float BorderThickness { get; set; } = 1f; /* ───────── 状态 ───────── */ private bool _hover; /* ───────── ctor ───────── */ public CircleButton() { SetStyle(ControlStyles.AllPaintingInWmPaint | ControlStyles.UserPaint | ControlStyles.OptimizedDoubleBuffer, true); FlatStyle = FlatStyle.Flat; FlatAppearance.BorderSize = 0; BackColor = Color.Red; ForeColor = Color.White; SyncSize(); MouseEnter += (_, __) => SetHover(true); MouseLeave += (_, __) => SetHover(false); } /* ───────── 重绘 ───────── */ protected override void OnResize(EventArgs e) { base.OnResize(e); UpdateRegion(); } protected override void OnPaint(PaintEventArgs e) { base.OnPaint(e); e.Graphics.SmoothingMode = SmoothingMode.AntiAlias; // ① 画圆填充 using (SolidBrush br = new SolidBrush(BackColor)) { e.Graphics.FillEllipse(br, 0, 0, Width, Height); } // ② 画边框(可选) if (BorderColor.A > 0 && BorderThickness > 0) { using (Pen pen = new Pen(BorderColor, BorderThickness)) { Rectangle rc = new Rectangle( (int)(BorderThickness / 2), (int)(BorderThickness / 2), Width - (int)BorderThickness, Height - (int)BorderThickness); e.Graphics.DrawEllipse(pen, rc); } } // ③ 绘制数字 if (_number > 0) { string txt = _number > 99 ? "99" : _number.ToString(); using (SolidBrush fb = new SolidBrush(ForeColor)) using (StringFormat sf = new StringFormat { Alignment = StringAlignment.Center, LineAlignment = StringAlignment.Center }) { e.Graphics.DrawString(txt, Font, fb, new RectangleF(0, 0, Width, Height), sf); } } } /* ───────── 私有助手 ───────── */ private void SetHover(bool hover) { if (_hover == hover) return; _hover = hover; BackgroundImage = hover && ImageHover != null ? ImageHover : _imgNormal; } private void SyncSize() { Width = Height = _radius * 2; UpdateRegion(); Invalidate(); } private void UpdateRegion() { try { GraphicsPath gp = new GraphicsPath(); gp.AddEllipse(0, 0, Width, Height); Region?.Dispose(); Region = new Region(gp); } catch (Exception ex) { Debug.WriteLine(ex); } } /* 隐藏 Size(设计器防误改) */ [EditorBrowsable(EditorBrowsableState.Never)] [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] public new Size Size { get => base.Size; set => base.Size = value; } public void SetMenuNum(int num) { if (SystemInfo.Instance.DisableShowNotify || num < 1) { this.Visible = false; return; } this.Number = num; this.Visible = true; } } }