纯手撸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。
效果如下:
三、代码以及思路
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);
五、nuget下载使用
1.nuget包管理器控制台
Install-Package Alert_Form -Version 1.1.2.2
2.nuget包管理器GUI下载
注:
1.这个包并不会长期维护,因为我只是为了学习nuget发布包以及自己写winform项目会用到而弄的。
2.自己封装其实主要是为了学习和改变对winform丑的看法,实际上现在已经有很多winform的UI框架了,比如:SunnyUI、HZHControls、SyncfusionUI等。自己造没有太大的必要。对于字体自适应,我这里也做的不好,文字太多了字号就会小到看不清。主要还是以学习为主。
版权声明
本文首发链接为:https://www.cnblogs.com/hyx1229/p/15801474.html
作者:不想只会CURD的猿某人
更多原著文章请参考:https://www.cnblogs.com/hyx1229/
转 https://www.cnblogs.com/hyx1229/p/15801474.html