I have created NotificationForm to replace MessageBox, The notifications appear above each other, and wait 5 sec to disappear. Whenever a notification disappears the above ones go down to their new positions.
The only problem I got is when another thread creates a new notification, I got error of Cross-thread. I tried Invoke and HandleCreate and it didn't solve the problem.
Here is the code:
NotificationAlertForm
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Windows.Forms;
using School.Properties;
namespace School.Forms
{
    public partial class NotificationAlert : Form
    {
        public enum enmAction
        {
            wait,
            start,
            close
        }
        public enum enmType
        {
            Success,
            Location,
            Error,
            Database
        }
        private static readonly List<NotificationAlert> activeAlerts = new List<NotificationAlert>();
        private enmAction action;
        private int x, y;
        public NotificationAlert()
        {
            InitializeComponent();
        }
        private void button1_Click(object sender, EventArgs e)
        {
            timer1.Interval = 1;
            action = enmAction.close;
        }
        private void timer1_Tick(object sender, EventArgs e)
        {
            switch (action)
            {
                case enmAction.wait:
                    timer1.Interval = 5000;
                    action = enmAction.close;
                    break;
                case enmAction.start:
                    timer1.Interval = 1;
                    Opacity += 0.1;
                    if (x < Location.X)
                    {
                        Left--;
                    }
                    else
                    {
                        if (Opacity == 1.0) action = enmAction.wait;
                    }
                    break;
                case enmAction.close:
                    var newY = 0;
                    // Remove the current alert from the list of active alerts
                    activeAlerts.Remove(this);
                    // Start a timer to gradually update the positions of the remaining alerts
                    var positionTimer = new Timer();
                    positionTimer.Interval = 250;
                    positionTimer.Tick += (ssender, args) =>
                    {
                        // Update the position of each remaining alert
                        var offset = 0;
                        foreach (var alert in activeAlerts)
                        {
                            alert.Invoke((Action)delegate ()
                            {
                                newY = Screen.PrimaryScreen.WorkingArea.Height - alert.Height * (offset + 1) -
                                       5 * offset;
                                if (alert.y != newY)
                                {
                                    // Update the y-coordinate of the alert gradually in small steps
                                    var step = Math.Sign(newY - alert.y) * 5;
                                    if (Math.Abs(newY - alert.y) < Math.Abs(step))
                                        alert.y = newY;
                                    else
                                        alert.y += step;
                                    alert.Location = new Point(alert.x, alert.y);
                                }
                                offset++;
                            });
                        }
                        // Stop the timer when all positions are updated
                        if (activeAlerts.Count == 0 || activeAlerts.All(a => a.y == newY)) positionTimer.Stop();
                    };
                    positionTimer.Start();
                    // Fade out and close the current alert
                    timer1.Interval = 1;
                    Opacity -= 0.1;
                    Left -= 3;
                    if (Opacity == 0.0) Close();
                    break;
            }
        }
        public void showAlert(string msg, enmType type)
        {
            // Add the new alert to the list of active alerts
            activeAlerts.Add(this);
            // Adjust the positions of all the active alerts
            var offset = 0;
            foreach (var alert in activeAlerts)
            {
                alert.y = Screen.PrimaryScreen.WorkingArea.Height - alert.Height * (offset + 1) - 5 * offset;
                if (!alert.IsHandleCreated)
                {
                    alert.CreateHandle();
                }
                alert.Invoke((Action)delegate ()
                {
                    alert.Location = new Point(alert.x, alert.y);
                    offset++;
                });
            }
            Opacity = 0.0;
            StartPosition = FormStartPosition.Manual;
            string fname;
            for (var i = 1; i < 10; i++)
            {
                fname = "alert" + i;
                var frm = (NotificationAlert)Application.OpenForms[fname];
                if (frm == null)
                {
                    Name = fname;
                    x = Screen.PrimaryScreen.WorkingArea.Width - Width + 15;
                    y = Screen.PrimaryScreen.WorkingArea.Height - Height * i - 5 * i;
                    Location = new Point(x, y);
                    break;
                }
            }
            x = Screen.PrimaryScreen.WorkingArea.Width - Width - 5;
            switch (type)
            {
                case enmType.Success:
                    pictureBox1.Image = Resources.icons8_ok_45px_1;
                    BackColor = Color.RoyalBlue;
                    break;
                case enmType.Error:
                    pictureBox1.Image = Resources.icons8_error_45px_1;
                    BackColor = Color.DarkRed;
                    break;
                case enmType.Database:
                    pictureBox1.Image = Resources.icons8_database_view_45px;
                    BackColor = Color.SeaGreen;
                    break;
                case enmType.Location:
                    pictureBox1.Image = Resources.icons8_location_45px;
                    BackColor = Color.OrangeRed;
                    break;
            }
            msg_text.Text = msg;
            TopMost = true;
            Show();
            action = enmAction.start;
            timer1.Interval = 1;
            timer1.Start();
        }
    }
}
NotificationAlertClass:
public static class NotificationAlertClass
    {
        public static void MessageSentSuccess(string msg)
        {
                var frm = new NotificationAlert();
                frm.showAlert(msg, NotificationAlert.enmType.Success);
        }
        public static void LocationSentSuccess(string msg)
        {
            var frm = new NotificationAlert();
            frm.showAlert(msg, NotificationAlert.enmType.Location);
        }
        public static void Error(string msg)
        {
            var frm = new NotificationAlert();
            frm.showAlert(msg, NotificationAlert.enmType.Error);
        }
        public static void DatabaseSuccess(string msg)
        {
           
                var frm = new NotificationAlert();
                frm.showAlert(msg, NotificationAlert.enmType.Database);
            
        }
    }
Tried MethodInvoke, it says that form handle must be created first, so I tried createHandle and still not works,
The only problem appears when another thread calls the class to start new Notificaiton