C# WinForm - 在按钮或其他控件的右上角绘制红点(带数字),如 android / ios apps

C# WinForm - Draw red point (with number) like android / ios apps on top right of button or other control

画红点如android / ios apps,用户注意有新事件。

是否有一个简单的案例来构建某些控件?

比如TabPage标题右上,Button右上,Groupbox右上。

我想到了两个遵循相同概念的想法。在 Winforms 中,您可以通过 PaintEvents 绘制 GDI 可能绘制​​的所有内容。因此,正如@Kinect 所提到的,没有用于处理此问题的内置解决方案。

这两个想法对你有用:

  1. 为您需要 RedPoint 的一切创建自定义控件。因此,您可以创建一个自己的框架,它扩展了所有基本 Winforms 并扩展了它(也许存在一些第三方的东西)。
  2. 您创建一个组件来为您处理绘画。

对于第一种方法,我创建了一个扩展 Button 并附加 RedPoint 绘图的小示例:

public class CustomButton : Button
{
    protected override void OnPaint(PaintEventArgs pevent)
    {
       base.OnPaint(pevent); //Call base for creating default Button

       using (Pen pen = new Pen(Color.Red, 3)) //Create small Red Pen
       {
            //Create the area we want to draw. In this case we draw at the Button top right corner (because Android, iOS do this)
            Rectangle rectangle = new Rectangle(pevent.ClipRectangle.X + pevent.ClipRectangle.Width - 10, 0, 10, 10);

            pevent.Graphics.DrawEllipse(pen, rectangle); //Draw a ellipse
            pevent.Graphics.FillEllipse(new SolidBrush(Color.Red), rectangle); //Fill this ellipse to be red

                //Paint a string to the ellipse so that it looks like Android, iOS Notification
                //You have to replace the 1 with dynamic count of your notifications
             pevent.Graphics.DrawString("1", DefaultFont, new SolidBrush(Color.White), rectangle.X, rectangle.Y);
        }
    }
}

你需要做某事。对于您要扩展的每个控件都这样。

或者您选择第二种方式并使用组件:

 public partial class RedPointDrawer : Component
    {
        /// <summary>
        /// Get: Dictionary of bound Controls which become a RedPoint with number of notifications
        /// </summary>
        public Dictionary<Control, int> Controls { get; }

        /// <summary>
        /// 
        /// </summary>
        public RedPointDrawer()
        {
            InitializeComponent();
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="container"></param>
        public RedPointDrawer(IContainer container)
        {
            container.Add(this);
            InitializeComponent();
            Controls = new Dictionary<Control, int>();
        }

        /// <summary>
        /// Draws a RedPoint to all 
        /// </summary>
        public void ActivateRedPoint()
        {
            foreach (Control control in Controls.Keys)
            {
                control.Paint += Control_Paint;
            }
        }

        private void Control_Paint(object sender, PaintEventArgs e)
        {
            int count;
            var control = sender as Control;

            if (control != null &&
                Controls.TryGetValue(control, out count))
            {
                using (Pen pen = new Pen(Color.Red, 3))
                {
                    Rectangle rectangle = new Rectangle(e.ClipRectangle.X + e.ClipRectangle.Width - 10, 0, 10, 10);

                    e.Graphics.DrawEllipse(pen, rectangle);
                    e.Graphics.FillEllipse(new SolidBrush(Color.Red), rectangle);
                    e.Graphics.DrawString(count.ToString(), new Font(new FontFamily("Arial"), 8), new SolidBrush(Color.White),
                        rectangle.X,
                        rectangle.Y);
                }
            }
        }
    }

因为组件拥有来自 Control 类型的字典,所以您可以 link 每个扩展 Control 的 Winform 对象(最多)。可以从您的工具箱中选择该组件并将其添加到您的表单中。然后在您的表单启动例程中调用以下代码:

private void FormStartUp() //Shown event or sth.
{
   redPointDrawer1.Controls.Add(button1, notifications.Count);
   redPointDrawer1.Controls.Add(button2, notifications2.Count);
   redPointDrawer1.ActivateRedPoint();
}

两种解决方案都会导致某事。像这样:

嗯,这并不完美,但对你来说可能是一个很好的起点。