Files
lserp_cs_6.0/插件库/Lskj.Control/CircleButton.cs
2026-07-02 10:11:39 +00:00

170 lines
5.4 KiB
C#

/***************************************************
* 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;
}
}
}