using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; using Электронная_Фармация.Classes; namespace Электронная_Фармация.HelpForms { public partial class NotificationForm : Form { private Timer animTimer; private int stage = 0; // 0 - появление, 1 - ожидание, 2 - уход private int displayTimeCount = 0; public int targetY_Move; private Timer moveTimer; private const int MoveSpeed = 10; // Скорость перемещения вверх // Настройки анимации private const int AnimationSpeed = 15; // Скорость сдвига (пикселей за тик) private const int DisplayDuration = 3000; // Сколько миллисекунд висит уведомление (3 секунды) public int targetX; public int startX; public NotificationForm(string message, Color backgroundColor, Color textColor) { InitializeComponent(); // Базовые настройки окна (чтобы не было рамок, кнопок и в панели задач) this.FormBorderStyle = FormBorderStyle.None; this.StartPosition = FormStartPosition.Manual; this.ShowInTaskbar = false; this.TopMost = true; this.BackColor = backgroundColor; // Настройка текста lblMessage.Text = message; lblMessage.ForeColor = textColor; // Инициализация таймера анимации animTimer = new Timer(); animTimer.Interval = 15; // ~60 FPS animTimer.Tick += AnimTimer_Tick; } public void MoveToY(int newY) { targetY_Move = newY; // Если таймер перемещения еще не создан, создаем его if (moveTimer == null) { moveTimer = new Timer(); moveTimer.Interval = 15; // Такая же частота, как у основного таймера moveTimer.Tick += MoveTimer_Tick; } // Если форма еще не находится в целевой позиции, запускаем таймер if (this.Top != targetY_Move) { moveTimer.Start(); } } private void MoveTimer_Tick(object sender, EventArgs e) { // Плавное перемещение вверх или вниз if (this.Top > targetY_Move) { this.Top -= MoveSpeed; if (this.Top < targetY_Move) this.Top = targetY_Move; } else if (this.Top < targetY_Move) { this.Top += MoveSpeed; if (this.Top > targetY_Move) this.Top = targetY_Move; } else { // Целевая позиция достигнута, останавливаем таймер moveTimer.Stop(); } } protected override void OnLoad(EventArgs e) { base.OnLoad(e); // Получаем рабочую область экрана (исключая панель задач) Rectangle workingArea = Screen.PrimaryScreen.WorkingArea; // Целевая позиция (в правом нижнем углу с небольшим отступом в 10px) targetX = workingArea.Right - this.Width - 10; int targetY = workingArea.Bottom - this.Height - 10; targetY_Move = targetY; // Инициализируем targetY_Move // Начальная позиция (за пределами экрана справа) startX = workingArea.Right; this.Location = new Point(startX, targetY); // Запускаем анимацию animTimer.Start(); } //protected override void Dispose(bool disposing) //{ // if (disposing) // { // if (components != null) components.Dispose(); // if (moveTimer != null) // { // moveTimer.Stop(); // moveTimer.Dispose(); // } // } // base.Dispose(disposing); //} private void AnimTimer_Tick(object sender, EventArgs e) { if (stage == 0) // Плавный выезд влево { if (this.Left > targetX) { this.Left -= AnimationSpeed; // Корректируем, чтобы не проскочить цель if (this.Left < targetX) this.Left = targetX; } else { stage = 1; // Переходим к фазе ожидания } } else if (stage == 1) // Ожидание { displayTimeCount += animTimer.Interval; if (displayTimeCount >= DisplayDuration) { stage = 2; // Пора закрываться } } else if (stage == 2) // Плавный уход вправо { if (this.Left < startX) { this.Left += AnimationSpeed; } else { animTimer.Stop(); animTimer.Dispose(); // ПЕРЕД закрытием удаляем форму из списка активных в менеджере! ToastNotification.RemoveNotification(this); this.Close(); // Уничтожаем форму после ухода } } } // Позволяет закрыть уведомление кликом по нему private void NotificationForm_Click(object sender, EventArgs e) { stage = 2; // Сразу переключаем на закрытие } } }