C#winform实现气泡碰撞电脑桌面边缘(碰撞后改变气泡颜色,支持添加气泡)

C#winform实现气泡碰撞电脑桌面边缘

  • 1 使用说明
  • 2 Form代码
  • 3 工具类代码

1 使用说明

  • 添加一个Form1,将Form1.cs的代码替换掉
  • 并引入工具类

效果图

2 Form代码

using System;
using System.Drawing;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace Test.QiPao
{
    public partial class FrmBubble : Form
    {
        /// 
        /// 当前气泡数量
        /// 
        public static int BubbleCount = 1;

        private string _name1 = "姓名1", _name2 = "姓名2";

        private readonly Random _random = new Random();

        /// 
        /// 气泡移动时间间隔,单位:毫秒
        /// 
        private int _nInterval = 10;

        /// 
        /// 气泡每次移动的距离
        /// 
        private float _step = 5;

        /// 
        /// 气泡的直径
        /// 
        private int _size = 300;

        /// 
        /// 气泡移动的直线方程k,b值
        /// 
        private float _dK = -1, _dB = 3;

        /// 
        /// 气泡上次位置
        /// 
        private PointF _lastPoint;

        /// 
        /// 气泡(左上角)活动的范围
        /// 
        private int _dScreenWidth, _dScreenHeight;

        /// 
        /// 气泡移动的方向
        /// 
        private E_LF _eLf = E_LF.RIGHT;

        /// 
        /// 现场运行状态
        /// 
        private bool _isRunning = true;

        private Label _lblBubbleText;



        /// 
        /// 气泡碰撞
        /// 
        public FrmBubble()
        {
            if (BubbleCount > 10) return;
            InitializeComponent();
            this.ContextMenuStrip = Bubble.GetBubbleContextMenuStrip(() => { Bubble.RefreshForm(this, () => new FrmBubble().Show()); });

            this.FormClosing += (sender, args) => _isRunning = false;
            Init();
        }

        private void Init()
        {
            var maxSize = Math.Min(Screen.PrimaryScreen.Bounds.Width, Screen.PrimaryScreen.Bounds.Height);
            _size = Math.Max(120, Math.Min(_size, maxSize));
            _lblBubbleText = Bubble.GetLabel(_size);
            this.Controls.Add(_lblBubbleText);
            SetBubbleStyle();
            this.Region = new Region(Bubble.CreateHeartPath(this, _size));

            _dScreenWidth = Screen.PrimaryScreen.Bounds.Width - this.Width;
            _dScreenHeight = Screen.PrimaryScreen.Bounds.Height - this.Height;

            _dK = BubbleCount++ % 2 == 0 ? -1 : 1;
            _dB = _random.Next(0, _dScreenHeight);
            if (_dB > _dScreenHeight) _dB = 1;
            _lastPoint = new PointF(_dK < 0 ? 0 : _dScreenWidth, _dB);

            new Task(BubbleMoveThread).Start();
        }

        private void BubbleMoveThread()
        {
            while (_isRunning)
            {
                try
                {
                    Thread.Sleep(_nInterval);
                    UpdataLocation(out float x, out float y);
                    _lastPoint.X = x;
                    _lastPoint.Y = y;

                    Bubble.RefreshForm(this, () =>
                     {
                         this.Left = (int)_lastPoint.X;
                         this.Top = (int)_lastPoint.Y;
                     });
                }
                catch (Exception ex)
                {
                    Console.WriteLine(ex.Message);
                }
            }
        }

        private void SetBubbleStyle()
        {
            Bubble.RefreshForm(this, () =>
            {
                try
                {
                    var index = _random.Next(0, Bubble.BubbleColor.Length);
                    this.BackColor = Bubble.BubbleColor[index];
                    _lblBubbleText.Text = _dK > 0 ? _name1 : _name2;
                    _lblBubbleText.ForeColor = Bubble.GetInverseColor(Bubble.BubbleColor[index]);
                }
                catch
                {

                }
            });
        }

        private void UpdataKB()
        {
            SetBubbleStyle();
            _dK *= -1;
            _dB = _lastPoint.Y - _dK * _lastPoint.X;
        }

        private void UpdataLocation(out float x, out float y)
        {
            x = _lastPoint.X + (_eLf == E_LF.RIGHT ? _step : -_step);
            if (x > _dScreenWidth)
            {
                UpdataKB();
                _eLf = E_LF.LEFT;
            }

            if (x < 0)
            {
                UpdataKB();
                _eLf = E_LF.RIGHT;
            }
            x = _lastPoint.X + (_eLf == E_LF.RIGHT ? _step : -_step);
            y = GetY(x);
            if (y < 0 || y > _dScreenHeight)
            {
                UpdataKB();
                UpdataLocation(out x, out y);
            }
        }

        private float GetY(float x) => _dK * x + _dB;

        public enum E_LF { LEFT, RIGHT }

    }
}

3 工具类代码

using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Reflection;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace Test.QiPao
{
    public class Bubble
    {

        /// 
        /// 存储气泡颜色集合
        /// 
        public static Color[] BubbleColor;

        static Bubble()
        {
            BubbleColor = GetCommonColors();
        }

        /// 
        /// 设置气泡窗体的基本属性
        /// 
        /// 
        private static void SetFormStyle(Form form, float size)
        {
            form.ShowInTaskbar = false;
            form.FormBorderStyle = FormBorderStyle.None; //先把窗体设置为无边框的样式
            form.TopMost = true;
            form.Opacity = 0.7; //设置窗体的不透明度为0.7相反就是窗体的透明度为0.3
            form.Size = new Size((int)size, (int)size);
        }

        /// 
        /// 获取圆形
        /// 
        public static GraphicsPath CreateCirclePath(Form form, float size)
        {
            SetFormStyle(form, size);
            GraphicsPath path = new GraphicsPath();
            path.AddEllipse(0, 0, size, size);
            return path;
        }

        /// 
        /// 获取心形
        /// 
        public static GraphicsPath CreateHeartPath(Form form, float size)
        {
            SetFormStyle(form, size);
            GraphicsPath path = new GraphicsPath();
            float width = size;
            float height = size - size / 8;

            // 定义心形的参数方程
            float t;
            for (t = 0; t <= 2 * Math.PI; t += 0.01f)
            {
                float x = 16 * (float)Math.Pow(Math.Sin(t), 3);
                float y = -(13 * (float)Math.Cos(t) - 5 * (float)Math.Cos(2 * t) - 2 * (float)Math.Cos(3 * t) - (float)Math.Cos(4 * t));

                // 将参数方程的坐标转换为窗体的坐标
                x = x * width / 32 + width / 2;
                y = y * height / 26 + height / 2;

                if (t == 0)
                {
                    path.StartFigure();
                }
                else
                {
                    path.AddLine(new PointF(x, y), new PointF(x, y));
                }
            }
            path.CloseFigure();

            return path;
        }

        /// 
        /// 气泡标签
        /// 
        /// 
        /// 
        public static Label GetLabel(float formSize)
        {
            Label lbl = new Label
            {
                Dock = DockStyle.Fill,
                Font = new Font("华文楷体", formSize / 10, FontStyle.Regular, GraphicsUnit.Point, 134),
                Location = new Point(0, 0),
                TabIndex = 0,
                TextAlign = ContentAlignment.MiddleCenter
            };
            return lbl;
        }

        /// 
        /// 获取颜色的互补色
        /// 
        public static Color GetInverseColor(Color color)
        {
            int red = 255 - color.R;
            int green = 255 - color.G;
            int blue = 255 - color.B;
            return Color.FromArgb(red, green, blue);
        }

        /// 
        /// 获取常见颜色
        /// 
        public static Color[] GetCommonColors()
        {
            var colors = new List<Color>();
            var properties = typeof(Color).GetProperties(BindingFlags.Public | BindingFlags.Static);
            for (var index = 0; index < properties.Length; index++)
            {
                var property = properties[index];
                if (property.PropertyType == typeof(Color))
                {
                    Color color = (Color)property.GetValue(null);
                    colors.Add(color);
                }
            }
            return colors.ToArray();
        }

        public static ContextMenuStrip GetBubbleContextMenuStrip(Action callback)
        {
            var contextMenuStrip = new ContextMenuStrip();

            //var comboBox = new ToolStripComboBox();
            //comboBox.DropDownStyle = ComboBoxStyle.Simple;
            //for (int i = 1; i < 11; i++)
            //{
            //    comboBox.Items.Add(i.ToString());
            //}
            //comboBox.SelectedIndex = 0;
            //contextMenuStrip.Items.Add(comboBox);

            var menuAddBubble = new ToolStripMenuItem { Text = "添加气泡" };
            menuAddBubble.Click += (sender, args) =>
            {
                //int.TryParse(comboBox.Text, out var count);
                int count = 3;
                new Task(() =>
                {
                    for (int i = 0; i < count; i++)
                    {
                        Thread.Sleep(1000);
                        callback?.Invoke();
                    }
                }).Start();
            };
            contextMenuStrip.Items.Add(menuAddBubble);

            return contextMenuStrip;
        }


        public static void RefreshForm(Form form, Action eventRefresh)
        {
            if (form.InvokeRequired)
            {
                form.Invoke(new EventHandler(delegate { RefreshForm(form, eventRefresh); }));
            }
            else
            {
                eventRefresh?.Invoke();
            }
        }
    }
}


你可能感兴趣的:(#,Winform,C#,#,C#绘图,c#)