純手畫WinForm的Alert提示彈出框

不想只會CURD的猿某人發表於2022-01-14

純手畫WinForm的Alert彈框

一、窗體設定

設定以下屬性:

屬性名 屬性值 說明
AutoScaleMode None 確定螢幕解析度或字型更改時窗體如何縮放
BackColor 103, 194, 58 背景色
Font Microsoft Sans Serif, 14.25pt 字型
FormBorderStyle None 標題欄和邊框樣式
ShowIcon False 是否顯示窗體圖示
ShowInTaskBar False 是否顯示在Windows工作列
Size 450,100 窗體大小
TopMost True 視窗置頂

二、介面控制元件

兩個PictureBox和一個Label以及一個定時器,控制元件大小大家自己定義吧,PictureBox設定SizeMode的值為Zoom,Label的ForeColor為white,AutoSIze為True。

效果如下:

image

三、程式碼以及思路

1.首先新建三個列舉類:AlertTypes.cs、ActionType.cs、ShowDirection.cs

AlertTypes控制彈框的型別,ActionType彈框的狀態,ShowDirection彈框的顯示位置

public enum AlertType
{
    /// <summary>
    /// 成功
    /// </summary>
    Success,
    /// <summary>
    /// 提示
    /// </summary>
    Info,
    /// <summary>
    /// 錯誤
    /// </summary>
    Error,
    /// <summary>
    /// 警告
    /// </summary>
    Warning
}
public enum ActionType
{
    /// <summary>
    /// 等待
    /// </summary>
    wait,
    /// <summary>
    /// 開啟
    /// </summary>
    start,
    /// <summary>
    /// 關閉
    /// </summary>
    close
}
public enum ShowDirection
{
    /// <summary>
    /// 頭部中心
    /// </summary>
    TopCenter,
    /// <summary>
    /// 右下角
    /// </summary>
    BottomRight,
    /// <summary>
    /// 右上角
    /// </summary>
    TopRight,
}

2.思路

1.滑動的效果通過可以通過定時器修改位置

2.隱藏的效果可以通過控制透明度

3.每一種型別的Alert最多隻能彈出10個

3.程式碼實現

1.公共變數

/// <summary>
/// Alert型別
/// </summary>
private ActionType action;
/// <summary>
/// 位置Point
/// </summary>
private int x, y;
/// <summary>
/// 動畫持續的時間
/// </summary>
private int Duration;
/// <summary>
/// 彈出的位置
/// </summary>
private ShowDirection Direction;

2.showAlert方法

  • 定義窗體的初始位置以及窗體最後的位置並呼叫this.Show()
  • 設定行為狀態為ActionType.start
  • 啟動定時器
/// <summary>
/// 內部呼叫顯示窗體
/// </summary>
/// <param name="msg"></param>
protected void ShowAlert(string msg)
{
    this.Opacity = 0.0;
    this.StartPosition = FormStartPosition.Manual;

    string fname;

    for (int i = 1; i < 10; i++)
    {
        fname = "alert" + i.ToString() + Direction.ToString();
        AlertForm frm = (AlertForm)Application.OpenForms[fname];
        if (frm == null)
        {
            this.Name = fname;
            // 初始位置
            switch (Direction)
            {
                case ShowDirection.TopCenter:
                    this.x = (Screen.PrimaryScreen.WorkingArea.Width - this.Width) / 2;
                    this.y = this.Height * i + 5 * i;
                    break;
                case ShowDirection.BottomRight:
                    this.x = Screen.PrimaryScreen.WorkingArea.Width - this.Width + 15;
                    this.y = Screen.PrimaryScreen.WorkingArea.Height - this.Height * i - 5 * i;
                    break;
                case ShowDirection.TopRight:
                    this.x = Screen.PrimaryScreen.WorkingArea.Width - this.Width + 15;
                    this.y = this.Height * i + 5 * i;
                    break;
            }
            this.Location = new Point(this.x, this.y);
            break;
        }
    }

    // 橫向最後的顯示位置 形成滑動距離
    switch (Direction)
    {
        case ShowDirection.BottomRight:
        case ShowDirection.TopRight:
            this.x = Screen.PrimaryScreen.WorkingArea.Width - base.Width - 5;
            break;
    }

    this.lbMsg.Text = msg;
    //字型大小自適應
    LabelAutoSize();
    this.Show();
    this.action = ActionType.start;
    this.hideTimer.Interval = 1;
    this.hideTimer.Start();
}

3.定時器事件控制動畫效果

private void hideTimer_Tick(object sender, EventArgs e)
{
    switch (this.action)
    {
        case ActionType.wait:
            this.hideTimer.Interval = Duration;
            this.action = ActionType.close;
            break;
        case ActionType.start:
            this.hideTimer.Interval = 1;
            this.Opacity += 0.1;
            switch (Direction)
            {
                case ShowDirection.TopCenter:
                    if (this.Opacity.Equals(1.0))
                    {
                        this.action = ActionType.wait;
                    }
                    break;
                case ShowDirection.BottomRight:
                case ShowDirection.TopRight:
                    if (this.x < this.Location.X)
                    {
                        this.Left--;
                    }
                    else
                    {
                        if (this.Opacity.Equals(1.0))
                        {
                            this.action = ActionType.wait;
                        }
                    }
                    break;
            }
            break;
        case ActionType.close:
            this.hideTimer.Interval = 1;
            this.Opacity -= 0.1;
            if (Direction == ShowDirection.TopCenter)
                this.Top -= 10;
            else
                this.Left -= 3;

            if (base.Opacity == 0.0)
                base.Close();
            break;
    }
}

4.暴露給外部使用的ShowAlert方法

/// <summary>
/// 暴露的方法
/// </summary>
/// <param name="msg">內容</param>
/// <param name="type">彈出型別</param>
/// <param name="duration">展示時間 秒</param>
/// <param name="direction">位置</param>
public static void ShowAlert(string msg, AlertType type,
                             int duration = 3, ShowDirection direction = ShowDirection.TopCenter)
{
    AlertForm alert = new AlertForm();
    switch (type)
    {
        case AlertType.Success:
            alert.picAlertType.Image = Resources.Success;
            alert.BackColor = Color.FromArgb(103, 194, 58);
            break;
        case AlertType.Info:
            alert.picAlertType.Image = Resources.Info;
            alert.BackColor = Color.FromArgb(64, 158, 255);
            break;
        case AlertType.Error:
            alert.picAlertType.Image = Resources.Error;
            alert.BackColor = Color.FromArgb(245, 108, 108);
            break;
        case AlertType.Warning:
            alert.picAlertType.Image = Resources.Warning;
            alert.BackColor = Color.FromArgb(230, 162, 60);
            break;
    }
    alert.Duration = duration * 1000;
    alert.Direction = direction;
    alert.ShowAlert(msg);

}

5.關閉按鈕的事件

private void btnPicClose_Click(object sender, EventArgs e)
{
    this.hideTimer.Interval = 1;
    this.action = ActionType.close;
}

4.全部程式碼

using Alert_Form.Properties;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace Alert_Form.Component.Alert
{
    public partial class AlertForm : Form
    {
        /// <summary>
        /// Alert型別
        /// </summary>
        private ActionType action;
        private int x, y;
        /// <summary>
        /// 動畫持續的時間
        /// </summary>
        private int Duration;
        /// <summary>
        /// 彈出的位置
        /// </summary>
        private ShowDirection Direction;
        /// <summary>
        /// 暴露的方法
        /// </summary>
        /// <param name="msg">內容</param>
        /// <param name="type">彈出型別</param>
        /// <param name="duration">展示時間 秒</param>
        /// <param name="direction">位置</param>
        public static void ShowAlert(string msg, AlertType type,
            int duration = 3, ShowDirection direction = ShowDirection.TopCenter)
        {
            AlertForm alert = new AlertForm();
            switch (type)
            {
                case AlertType.Success:
                    alert.picAlertType.Image = Resources.Success;
                    alert.BackColor = Color.FromArgb(103, 194, 58);
                    break;
                case AlertType.Info:
                    alert.picAlertType.Image = Resources.Info;
                    alert.BackColor = Color.FromArgb(64, 158, 255);
                    break;
                case AlertType.Error:
                    alert.picAlertType.Image = Resources.Error;
                    alert.BackColor = Color.FromArgb(245, 108, 108);
                    break;
                case AlertType.Warning:
                    alert.picAlertType.Image = Resources.Warning;
                    alert.BackColor = Color.FromArgb(230, 162, 60);
                    break;
            }
            alert.Duration = duration * 1000;
            alert.Direction = direction;
            alert.ShowAlert(msg);

        }
        
        public AlertForm()
        {
            InitializeComponent();
        }

        private void btnPicClose_Click(object sender, EventArgs e)
        {
            this.hideTimer.Interval = 1;
            this.action = ActionType.close;
        }

        private void hideTimer_Tick(object sender, EventArgs e)
        {
            switch (this.action)
            {
                case ActionType.wait:
                    this.hideTimer.Interval = Duration;
                    this.action = ActionType.close;
                    break;
                case ActionType.start:
                    this.hideTimer.Interval = 1;
                    this.Opacity += 0.1;
                    switch (Direction)
                    {
                        case ShowDirection.TopCenter:
                            if (this.Opacity.Equals(1.0))
                            {
                                this.action = ActionType.wait;
                            }
                            break;
                        case ShowDirection.BottomRight:
                        case ShowDirection.TopRight:
                            if (this.x < this.Location.X)
                            {
                                this.Left--;
                            }
                            else
                            {
                                if (this.Opacity.Equals(1.0))
                                {
                                    this.action = ActionType.wait;
                                }
                            }
                            break;
                    }
                    break;
                case ActionType.close:
                    this.hideTimer.Interval = 1;
                    this.Opacity -= 0.1;
                    if (Direction == ShowDirection.TopCenter)
                        this.Top -= 10;
                    else
                        this.Left -= 3;

                    if (base.Opacity == 0.0)
                        base.Close();
                    break;
            }
        }
        /// <summary>
        /// 內部呼叫顯示窗體
        /// </summary>
        /// <param name="msg"></param>
        protected void ShowAlert(string msg)
        {
            this.Opacity = 0.0;
            this.StartPosition = FormStartPosition.Manual;

            string fname;

            for (int i = 1; i < 10; i++)
            {
                fname = "alert" + i.ToString() + Direction.ToString();
                AlertForm frm = (AlertForm)Application.OpenForms[fname];
                if (frm == null)
                {
                    this.Name = fname;
                    // 初始位置
                    switch (Direction)
                    {
                        case ShowDirection.TopCenter:
                            this.x = (Screen.PrimaryScreen.WorkingArea.Width - this.Width) / 2;
                            this.y = this.Height * i + 5 * i;
                            break;
                        case ShowDirection.BottomRight:
                            this.x = Screen.PrimaryScreen.WorkingArea.Width - this.Width + 15;
                            this.y = Screen.PrimaryScreen.WorkingArea.Height - this.Height * i - 5 * i;
                            break;
                        case ShowDirection.TopRight:
                            this.x = Screen.PrimaryScreen.WorkingArea.Width - this.Width + 15;
                            this.y = this.Height * i + 5 * i;
                            break;
                    }
                    this.Location = new Point(this.x, this.y);
                    break;
                }
            }

            // 橫向最後的顯示位置 形成滑動距離
            switch (Direction)
            {
                case ShowDirection.BottomRight:
                case ShowDirection.TopRight:
                    this.x = Screen.PrimaryScreen.WorkingArea.Width - base.Width - 5;
                    break;
            }

            this.lbMsg.Text = msg;
            //字型大小自適應
            LabelAutoSize();
            this.Show();
            this.action = ActionType.start;
            this.hideTimer.Interval = 1;
            this.hideTimer.Start();
        }
        /// <summary>
        /// msg文字大小自適應
        /// </summary>
        private void LabelAutoSize()
        {            
            Font font;
            while (true)
            {
                var lbFont = this.lbMsg.Font;
                if (lbMsg.Right >= this.btnPicClose.Left)
                {
                    font = new Font(lbFont.Name,lbFont.Size-1,lbFont.Style);
                    this.lbMsg.Font = font;
                }
                else
                {
                    var top = (this.Height - this.lbMsg.Height) / 2;
                    lbMsg.Top = top;
                    break;
                }
            }            
        }
    }
}

四、最終效果

呼叫:

AlertForm.ShowAlert("Success MessageText",AlertType.Success,direction:ShowDirection.BottomRight);
AlertForm.ShowAlert("Info MessageText", AlertType.Info,direction:ShowDirection.TopRight);
AlertForm.ShowAlert("Error MessageText", AlertType.Error);
AlertForm.ShowAlert("Warning MessageText",AlertType.Warning);

image

五、nuget下載使用

1.nuget包管理器控制檯

Install-Package Alert_Form -Version 1.1.2.2

2.nuget包管理器GUI下載

image

注:

1.這個包並不會長期維護,因為我只是為了學習nuget釋出包以及自己寫winform專案會用到而弄的。

2.自己封裝其實主要是為了學習和改變對winform醜的看法,實際上現在已經有很多winform的UI框架了,比如:SunnyUIHZHControlsSyncfusionUI等。自己造沒有太大的必要。對於字型自適應,我這裡也做的不好,文字太多了字號就會小到看不清。主要還是以學習為主。

版權宣告

本文首發連結為:https://www.cnblogs.com/hyx1229/p/15801474.html

作者:不想只會CURD的猿某人

更多原著文章請參考:https://www.cnblogs.com/hyx1229/

相關文章