纯手撸WinForm的Alert提示弹出框

纯手撸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/

posted @ 2022-01-14 13:21  不想只会CRUD的猿某人  阅读(4299)  评论(23编辑  收藏  举报