原来winform也可以很好看——纯手画WinForm的Alert弹框

纯手画WinForm的Alert弹框

一、窗体设置

设置以下属性:

属性名属性值说明
AutoScaleModeNone确定屏幕分辨率或字体更改时窗体如何缩放
BackColor103, 194, 58背景色
FontMicrosoft Sans Serif, 14.25pt字体
FormBorderStyleNone标题栏和边框样式
ShowIconFalse是否显示窗体图标
ShowInTaskBarFalse是否显示在Windows任务栏
Size450,100窗体大小
TopMostTrue窗口置顶

二、界面控件

两个PictureBox和一个Label以及一个定时器,控件大小大家自己定义吧,PictureBox设置SizeMode的值为Zoom,Label的ForeColor为white,AutoSIze为True。

效果如下:

image-20220113173016095

三、代码以及思路

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);

alerform

五、nuget下载使用

1.nuget包管理器控制台

Install-Package Alert_Form -Version 1.1.2.2

2.nuget包管理器GUI下载

image-20220114130628426

注:

1.这个包并不会长期维护,因为我只是为了学习nuget发布包以及自己写winform项目会用到而弄的。

2.自己封装其实主要是为了学习和改变对winform丑的看法,实际上现在已经有很多winform的UI框架了,比如:SunnyUIHZHControlsSyncfusionUI等。自己造没有太大的必要。对于字体自适应,我这里也做的不好,文字太多了字号就会小到看不清。主要还是以学习为主。

版权声明

本文首发链接为:https://www.cnblogs.com/hyx1229/p/15801474.html
两个平台作者为同一人。

  • 4
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
原来 WinFormWindows 窗体应用程序)也能做出精美的侧边菜单栏。WinForm 是 Microsoft .NET Framework 提供的一种用于构建 Windows 客户端应用程序的技术。它拥有丰富的控件库和强大的可视化设计工具,使开发人员能够轻松创建各种用户界面。 要实现精美的侧边菜单栏,可以使用 WinForm 提供的控件和布局功能。首先,我们可以使用 Panel 控件作为容器来承载菜单栏。Panel 控件具有可自定义的样式和布局功能,可以用于容纳其他控件。 在 Panel 中,可以添加菜单项按钮,可以使用 Button 或者 LinkLabel 控件来组合实现。这些控件都拥有丰富的设置项,可以进行外观和交互方式的定制,从而实现精美的效果。 同时,可以利用布局功能来实现自适应和响应式的菜单栏。例如,使用 TableLayoutPanel 或者 FlowLayoutPanel 控件来自动调整控件的位置和大小。这样,当窗口大小发生变化时,菜单栏的布局也会自动调整,确保界面的美观性和易用性。 另外,要实现动态菜单栏,可以通过编程的方式动态添加、移除或者隐藏菜单项。这样,就可以根据具体的业务需求来实现菜单栏的个性化定制。 总之,虽然 WinForm 是一个相对老旧的技术,但是它仍然具有许多强大的功能,可以用来实现精美的侧边菜单栏。开发人员可以充分利用 WinForm 提供的控件和布局功能,结合自己的创意和设计能力,创造出符合用户期望的用户界面。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

不想只会CRUD的猿某人

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值