共计 8346 个字符,预计需要花费 21 分钟才能阅读完成。
纯手撸 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/hyx12…
作者:不想只会 CURD 的猿某人
更多原著文章请参考:https://www.cnblogs.com/hyx1229/