windowcapture
исходный код / UI/ToastNotification.cs

ToastNotification.cs

152 строк · 5,025 байт · модуль UI
  1using System;
  2using System.Drawing;
  3using System.Windows.Forms;
  4
  5namespace WindowCapture.UI
  6{
  7    /// <summary>
  8    /// Toast notification that appears in the bottom-right corner of the screen
  9    /// </summary>
 10    public class ToastNotification : Form
 11    {
 12        private Timer fadeTimer;
 13        private Timer closeTimer;
 14        private Label lblTitle;
 15        private Label lblMessage;
 16        private int targetY;
 17        private bool isAnimatingIn = true;
 18
 19        public ToastNotification(string title, string message, bool isError = false)
 20        {
 21            // Form settings
 22            this.FormBorderStyle = FormBorderStyle.None;
 23            this.ShowInTaskbar = false;
 24            this.TopMost = true;
 25            this.StartPosition = FormStartPosition.Manual;
 26            this.Size = new Size(300, 80);
 27            this.BackColor = isError ? Color.FromArgb(60, 30, 30) : Color.FromArgb(30, 30, 30);
 28            this.Opacity = 0;
 29
 30            // Position in bottom-right corner
 31            var screen = Screen.PrimaryScreen.WorkingArea;
 32            targetY = screen.Bottom - this.Height - 10;
 33            this.Location = new Point(screen.Right - this.Width - 10, targetY + 50); // Start below target
 34
 35            // Border
 36            this.Paint += (s, e) =>
 37            {
 38                var borderColor = isError ? Color.FromArgb(180, 60, 60) : Color.FromArgb(0, 120, 215);
 39                using (var pen = new Pen(borderColor, 2))
 40                {
 41                    e.Graphics.DrawRectangle(pen, 1, 1, this.Width - 2, this.Height - 2);
 42                }
 43            };
 44
 45            // Title label
 46            lblTitle = new Label();
 47            lblTitle.Text = title;
 48            lblTitle.ForeColor = isError ? Color.FromArgb(255, 100, 100) : Color.FromArgb(0, 150, 255);
 49            lblTitle.Font = new Font("Segoe UI", 10f, FontStyle.Bold);
 50            lblTitle.Location = new Point(10, 8);
 51            lblTitle.Size = new Size(280, 22);
 52            lblTitle.BackColor = Color.Transparent;
 53            this.Controls.Add(lblTitle);
 54
 55            // Message label
 56            lblMessage = new Label();
 57            lblMessage.Text = message;
 58            lblMessage.ForeColor = Color.White;
 59            lblMessage.Font = new Font("Segoe UI", 9f);
 60            lblMessage.Location = new Point(10, 32);
 61            lblMessage.Size = new Size(280, 40);
 62            lblMessage.BackColor = Color.Transparent;
 63            this.Controls.Add(lblMessage);
 64
 65            // Click to close
 66            this.Click += (s, e) => this.Close();
 67            lblTitle.Click += (s, e) => this.Close();
 68            lblMessage.Click += (s, e) => this.Close();
 69
 70            // Fade in animation
 71            fadeTimer = new Timer();
 72            fadeTimer.Interval = 15;
 73            fadeTimer.Tick += FadeTimer_Tick;
 74            fadeTimer.Start();
 75
 76            // Auto close after delay
 77            closeTimer = new Timer();
 78            closeTimer.Interval = isError ? 5000 : 3000;
 79            closeTimer.Tick += (s, e) =>
 80            {
 81                closeTimer.Stop();
 82                isAnimatingIn = false;
 83                fadeTimer.Start();
 84            };
 85        }
 86
 87        private void FadeTimer_Tick(object sender, EventArgs e)
 88        {
 89            if (isAnimatingIn)
 90            {
 91                // Fade in and slide up
 92                if (this.Opacity < 1)
 93                {
 94                    this.Opacity += 0.1;
 95                }
 96
 97                if (this.Top > targetY)
 98                {
 99                    this.Top -= 5;
100                }
101                else
102                {
103                    this.Top = targetY;
104                }
105
106                if (this.Opacity >= 1 && this.Top <= targetY)
107                {
108                    fadeTimer.Stop();
109                    closeTimer.Start();
110                }
111            }
112            else
113            {
114                // Fade out
115                this.Opacity -= 0.1;
116                if (this.Opacity <= 0)
117                {
118                    fadeTimer.Stop();
119                    this.Close();
120                }
121            }
122        }
123
124        protected override void OnFormClosed(FormClosedEventArgs e)
125        {
126            if (fadeTimer != null) fadeTimer.Dispose();
127            if (closeTimer != null) closeTimer.Dispose();
128            base.OnFormClosed(e);
129        }
130
131        protected override CreateParams CreateParams
132        {
133            get
134            {
135                // Make window click-through friendly and tool window (no taskbar)
136                CreateParams cp = base.CreateParams;
137                cp.ExStyle |= 0x00000080; // WS_EX_TOOLWINDOW
138                return cp;
139            }
140        }
141
142        /// <summary>
143        /// Show a toast notification
144        /// </summary>
145        public static void Show(string title, string message, bool isError = false)
146        {
147            // Must be called on UI thread
148            var toast = new ToastNotification(title, message, isError);
149            toast.Show();
150        }
151    }
152}