WinForms app with Elfisa.UI, API integration, order workflow, invoices/refusals sync, and production-ready fixes from the desktop roadmap. Co-authored-by: Cursor <cursoragent@cursor.com>
173 lines
6.4 KiB
C#
173 lines
6.4 KiB
C#
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; // Сразу переключаем на закрытие
|
||
}
|
||
|
||
|
||
}
|
||
}
|