C# Winform实现自定义漂亮的通知效果

目录
  • 前言
  • 优化调整
  • 调用并显示自定义通知
  • 主要实现过程
  • 代码实现

前言

本文主要介绍其具体的实现思路(视频仅有代码输入,并无过程介绍等),同时,在原本实现的基础上,进行了多处修改和优化,具体参见下面的内容。

优化调整

下面是对源代码的修改、优化和调整:

  • 修改 lblMsg(Label) 的 AutoSize 为false,尽可能多占通知窗体区域,Anchor跟随窗体变换,文字左侧垂直居中,用于显示可能更多的消息.
  • 设定action、timer1默认值,Name、Opacity、StartPosition(Manual)在构造函数中指定,这样就不用每次创建通知窗体时进行赋值了。ShowInTaskbar = false;通知窗体不在任务栏显示。
  • 将原有代码中定时器时间间隔调整到100毫秒,原设置为1,时间太短人眼看不出区别,白白浪费计算。
  • ShowNotice()改为静态方法,直接通过Form_Alert.ShowNotice(msg, msgType);调用显示窗体,不用new创建对象再调用。
  • AlertFormNum静态属性设置最多显示的通知数量,默认尽可能多的占满垂直屏幕,手动设置数量不能低于1或超出屏幕。
  • ShowTime静态属性设置完全显示后通知的显示时间,单位毫秒;也可以扩展渐变显示和消失的时间。
  • MoveEntry静态属性设置消息框是否水平移动进入,默认true。通过设置初始的消息框位置,即可实现水平移动进入。
  • 实现消息框占满后,新的消息框替换最近消失的通知的功能。原实现中最多只能显示10个通知框,当再多时不会显示(丢失掉),只有腾出位置(通知消失后)才能显示新的,现在已经优化为超出的通知框会替换掉旧通知,不会丢失。

下图为示例,后半段显示的内容是设置最多显示5个消息框时,发生替换的效果;

// 设置通知的数量
Form_Alert.AlertFormNum = 5;
Form_Alert.MoveEntry = false;// 不水平移动进入
  • 调整下图标位置,垂直方向居中一些

水平移动进入的效果(默认):

  • 添加显示时指定消息字体的参数,有需要可直接修改显示文字的字体。
/// <summary>
/// 设置完x、y之后执行初始化启动。设置位置、消息类型、显示、倒计时
/// </summary>
/// <param name="msg"></param>
/// <param name="msgType"></param>
/// <param name="msgFont">字体,默认不指定即可</param>
private void InitStart(string msg, MsgType msgType, Font msgFont = null)
{
    // ...
}

调用并显示自定义通知

新建项目NotificationCustom,完成通知框的调用显示

Form_Alert.ShowNotice("这是一条成功的消息", MsgType.Success);

Form_Alert.ShowNotice("警告!警告的消息", MsgType.Warning);

Form_Alert.ShowNotice("发生了错误,禁止!", MsgType.Error);

Form_Alert.ShowNotice("一条普通的信息记录", MsgType.Info);

或者显示时指定字体(下面为随机字体)

Form_Alert.ShowNotice("这是一条成功的消息", MsgType.Success, new Font(FontFamily.Families[random.Next(0, FontFamily.Families.Length)], (float)(10.0+10.0*random.NextDouble())));

主要实现过程

  • 创建一个无边框窗体Form_Alert,添加Label(lblMsg)显示通知消息,添加一个表示关闭的图片(PictureBox)。
  • 设置窗体StartPosition = FormStartPosition.Manual;,后面用于设置其初始位置为指定的屏幕右下角
  • 通过不同的背景颜色、不同的图片(icon,PictureBox)代表不同的消息类型(MsgType)
  • 定时器中通过定时时间完成消息窗的显示(透明度变化)、显示一定时间、关闭(逐渐透明)整个流程:定义消息窗体不同的操作(NotificationFormAction),start表示开始显示,显示窗体并在定时器中处理透明、移入的显示过程,完全显示后改变操作状态为wait;设置消息窗体显示等待的时间,操作状态变为close,定时时间之后再次执行定时器进入close处理;close过程中定时器执行变得透明、移出,完全透明后关闭定时器、关闭窗体。
  • 点击关闭按钮图标,窗体状态变为close,定时时间改为close的间隔100
  • 每次定时器执行函数的结尾记录下次执行的时间,用于判断当两个窗体的状态相同时,剩余执行时间为多少,判断哪个窗体最先消失,用于完成后面的消息通知太多时,新旧消息框的替换【不严谨,尤其在逐渐的显示和关闭过程中,有着多次的定时器循环,如果想要完全严格,可以考虑计算消息窗体最终消失的时间(消息框的状态,循环执行的剩余次数,每次的间隔时间综合计算)】
  • ShowNotice()静态方法显示消息框,直接传递要显示的消息和消息类型即可,分为Success,Warning,Error,Info四类,通过指定的 AlertFormNum 消息框数量(或默认数量),循环依次显示消息框,并启动定时器处理消息框的窗体状态:渐变显示(透明度)、显示一定时间(ShowTime)、渐变消失。循环中通过Application.OpenForms[fname]获取通知框窗体,如果没有获取到则创建新窗体,并执行显示,结束整个显示处理;在循环中记录已有窗体中最先消失的窗体;如果全部循环完,则说明所有数量的通知框都存在,则完成对最先消失的窗体的替换并显示新的消息窗体。

代码实现

修改后全部代码不到200行,如下,主要部分已经进行注释:

namespace CustomAlertBoxDemo
{
    public enum NotificationFormAction
    {
        start,
        wait,
        close
    }
    public enum MsgType
    {
        Success,
        Warning,
        Error,
        Info
    }
    public partial class Form_Alert : Form
    {
        /// <summary>
        /// 通知窗体的数量,默认为垂直屏幕几乎占满的数量
        /// </summary>
        private static int alertFormNum = Screen.PrimaryScreen.WorkingArea.Height / (75 + 5); // 75为窗体高度,如果调整窗体高度,记得修改此处
        /// <summary>
        /// 通知窗体的数量,默认为垂直屏幕几乎占满的数量,手动修改的数量不能超出屏幕和低于1,否则设置无效
        /// </summary>
        public static int AlertFormNum
        {
            get => alertFormNum;
            set
            {
                if (value <= Screen.PrimaryScreen.WorkingArea.Height / (75 + 5) && value > 0)
                {
                    alertFormNum = value;
                }
            }
        }
        /// <summary>
        /// 自定义通知的显示时间,单位为毫秒,默认为3分钟,之后开始消失。可根据需要修改
        /// </summary>
        public static int ShowTime { get; set; } = 3000;
        /// <summary>
        /// 是否移动进入,默认true
        /// </summary>
        public static bool MoveEntry { get; set; } = true;
        /// <summary>
        /// 创建通知窗体
        /// </summary>
        /// <param name="name">窗体名称,必须指定</param>
        public Form_Alert(string name)
        {
            InitializeComponent();
            Name = name;
            this.Opacity = 0.0;
            ShowInTaskbar = false;
            StartPosition = FormStartPosition.Manual;
        }
        private NotificationFormAction action = NotificationFormAction.start;
        /// <summary>
        /// 当前消息框的标准位置
        /// </summary>
        private int x, y;
        private void timer1_Tick(object sender, EventArgs e)
        {
            switch (this.action)
            {
                case NotificationFormAction.wait:
                    timer1.Interval = ShowTime;
                    action = NotificationFormAction.close;
                    break;
                case NotificationFormAction.start:
                    this.timer1.Interval = 100;
                    this.Opacity += 0.1;
                    if (this.x < this.Location.X)
                    {
                        this.Left-=20; // 移动快点
                    }
                    else
                    {
                        if (this.Opacity == 1.0)
                        {
                            action = NotificationFormAction.wait;
                        }
                    }
                    break;
                case NotificationFormAction.close:
                    timer1.Interval = 100;
                    this.Opacity -= 0.1;
                    this.Left -= 20;
                    if (base.Opacity == 0.0)
                    {
                        timer1.Stop();
                        base.Close();
                    }
                    break;
            }
            // tag记录下次执行的时间,用于后续的替换
            timer1.Tag = DateTime.Now.AddMilliseconds(timer1.Interval);
        }
        private void pictureBox2_Click(object sender, EventArgs e)
        {
            timer1.Interval = 100;
            action = NotificationFormAction.close;
        }
        /// <summary>
        /// 设置完x、y之后执行初始化启动。设置位置、消息类型、显示、倒计时
        /// </summary>
        /// <param name="msg"></param>
        /// <param name="msgType"></param>
        private void InitStart(string msg, MsgType msgType)
        {
            //this.Location = new Point(frm.x, frm.y);
            this.Location = new Point(x + (MoveEntry?Width / 2:0), y);
            switch (msgType)
            {
                case MsgType.Success:
                    pictureBox1.Image = Resources.success;
                    BackColor = Color.SeaGreen;
                    break;
                case MsgType.Error:
                    pictureBox1.Image = Resources.error;
                    BackColor = Color.DarkRed;
                    break;
                case MsgType.Info:
                    pictureBox1.Image = Resources.info;
                    BackColor = Color.RoyalBlue;
                    break;
                case MsgType.Warning:
                    pictureBox1.Image = Resources.warning;
                    BackColor = Color.DarkOrange;
                    break;
            }
            lblMsg.Text = msg;
            Show();
            timer1.Start();
        }
        public static void ShowNotice(string msg, MsgType msgType)
        {
            Form_Alert willDisappearFrm = null;
            for (int i = 1; i < alertFormNum+1; i++)
            {
                string fname = "alert" + i.ToString();
                Form_Alert frm = (Form_Alert)Application.OpenForms[fname];
                if (frm == null)
                {
                    frm = new Form_Alert(fname);
                    frm.x = Screen.PrimaryScreen.WorkingArea.Width - frm.Width - 5;
                    frm.y = Screen.PrimaryScreen.WorkingArea.Height - frm.Height * i - 5 * i;
                    // 设置完x、y之后执行初始化启动
                    frm.InitStart(msg, msgType);
                    return;
                }
                else
                {
                    if (willDisappearFrm == null)
                    {
                        willDisappearFrm = frm;
                    }
                    else
                    {
                        if (willDisappearFrm.action < frm.action)
                        {
                            willDisappearFrm = frm;
                        }
                        else if (willDisappearFrm.action == frm.action)
                        {
                            // 不考虑一次没执行的情况
                            if (willDisappearFrm.timer1.Tag!=null&& frm.timer1.Tag != null)
                            {
                                if (willDisappearFrm.timer1.Tag == null)
                                {
                                    willDisappearFrm = frm;
                                }
                                else if(frm.timer1.Tag != null)
                                {
                                    if ((DateTime)willDisappearFrm.timer1.Tag > (DateTime)frm.timer1.Tag)
                                    {
                                        willDisappearFrm = frm;
                                    }
                                }
                            }
                        }
                    }
                }
            }
            // 当前最早要消失的窗体willDisappearFrm被替换
            var newfrm = new Form_Alert(willDisappearFrm.Name);
            newfrm.x = Screen.PrimaryScreen.WorkingArea.Width - newfrm.Width - 5;
            newfrm.y = willDisappearFrm.Location.Y;
            // 必须立即替换name
            var totalNum = 0;
            foreach (Form form in Application.OpenForms)
            {
                if (form is Form_Alert)
                {
                    totalNum += 1;
                }
            }
            willDisappearFrm.Name = $"Form_Alert{totalNum + 1}";
            willDisappearFrm.pictureBox2_Click(null, null);
            // 设置完x、y之后执行初始化启动
            newfrm.InitStart(msg, msgType);
        }
    }
}

到此这篇关于C# Winform实现自定义漂亮的通知效果的文章就介绍到这了,更多相关C# Winform通知效果内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • C# winform 请求http的实现(get,post)

    目录 一:.Net中有两个类 HttpWebRequest 和HttpWebResponse 类来实现Http的请求 二: HTTP定义了与服务器交互的不同方法 POST与GET的差异 两个简单的Get请求和Post请求 1.Get请求 2.Post请求 一个小测试 一:.Net中有两个类 HttpWebRequest 和HttpWebResponse 类来实现Http的请求 实现步骤: 1.通过WebRequest类创建一个HttpWebRequest的对象,该对象可以包含Http请求信息.2

  • C# WinForm制作登录界面的实现步骤

    在[解决方案资源管理器]中找到Form1.cs,单击,快捷键F2重命名为“Login.cs”(命名很重要,不然之后项目多了根据不知道哪个项目的内容是什么) 对窗体[Text]属性.[size]属性和[FormBoardStyle]属性进行修改 添加一个新的窗体 Ctrl+Shift+A,在弹出框中选择[Windows窗体],命名为main.cs 取消登录界面最大化最小化关闭按钮在父窗体菜单栏上显示最大化:MaximizeBox,最小化:MinimizeBox如果设置一个为False 的时候会显示

  • C# Winform消息通知之系统本地通知local toast notification

    目录 引言 toast 通知的结构 发送本地toast通知的操作步骤 安装NuGet包Microsoft.Toolkit.Uwp.Notifications 通知的发送(文本通知) 处理点击通知的操作 通知的卸载 设置通知的过期时间 .NET应用使用Toast Notifications(.NET5+) 添加图像 使用http图像 内联图像和主图 徽标和剪裁(圆形图片) UWP使用http图片 替换或删除指定通知 为 toast 设置主键 根据Tag和Group删除或替换toast 清除通知 引

  • C# Winform实现进度条显示

    本文实例为大家分享了C# Winform实现进度条显示的具体代码,供大家参考,具体内容如下 创建一个窗体,命名为StartForm 添加一个timer控件并更改名字为timerStart 添加一个ProgressBar控件,并调整一下属性: StartForm窗体的代码: using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Draw

  • C# Winform实现圆角无锯齿按钮

    前言: 发现用Winform做一个圆角按钮遇到麻烦,主要是锯齿问题,后面想了想办法解决问题了. 主要方法是按钮的区域通过Region指定,但按钮需要自己画,否则怎么搞都出现锯齿,网上有朋友提供一个漂亮的方案,可是代码不完整无法使用,我的解决方案现在分享如下: public enum ControlState { Hover , Normal, Pressed } public class RoundButton : Button { private int radius;//半径 private

  • C# Winform消息通知系统托盘气泡提示框ToolTip控件

    目录 气球状提示框的介绍和系统通知变化 消息通知的提示 ShowBalloonTip()方法及指定消息类型 NotifyIcon属性设置消息 BalloonTipIcon不同的消息类型 ToolTipText属性 ToolTip提示控件显式或主动的提示消息 一个ToolTip同时为多个控件设置提示 显式设置ToolTip 气球状提示框的介绍和系统通知变化 NotifyIcon控件表示系统右下角任务栏上的托盘图标,其ShowBalloonTip方法用于显示任务栏中一定时间的具有指定标题.消息内容和

  • C# Winform实现自定义漂亮的通知效果

    目录 前言 优化调整 调用并显示自定义通知 主要实现过程 代码实现 前言 本文主要介绍其具体的实现思路(视频仅有代码输入,并无过程介绍等),同时,在原本实现的基础上,进行了多处修改和优化,具体参见下面的内容. 优化调整 下面是对源代码的修改.优化和调整: 修改 lblMsg(Label) 的 AutoSize 为false,尽可能多占通知窗体区域,Anchor跟随窗体变换,文字左侧垂直居中,用于显示可能更多的消息. 设定action.timer1默认值,Name.Opacity.StartPos

  • WinForm实现自定义右下角提示效果的方法

    本文实例讲述了WinForm实现自定义右下角提示效果的方法.分享给大家供大家参考.具体实现方法如下: using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; namespace IcoFl

  • android通过自定义toast实现悬浮通知效果的示例代码

    android通过toast实现悬浮通知效果,如图: 实现的功能: 自定义悬浮弹窗: 点击其他地方该布局不受影响: 可自定义显示时间: 可以设置点击事件: 代码如下: import android.content.Context; import android.os.Build; import android.os.Handler; import android.os.Message; import android.support.v7.app.AppCompatActivity; import

  • 非常漂亮的新年祝福!C语言实现漂亮的烟花效果

    本文实例为大家分享了C语言实现漂亮的烟花效果展示的具体代码,供大家参考,具体内容如下 程序名称:祝福烟花,祝福朋友 编译环境:VC++6.0 && easyx(立冬版) #include <graphics.h> #include <conio.h> #include <iostream.h> #include <math.h> #include <time.h> #include <stdio.h> #include

  • Qt自定义Widget实现互斥效果详解

    目录 前沿 功能实现 知识点 问题 讲解知识点1 讲解知识点2 讲解知识点3 总结 前沿 什么叫做自定义Widget实现互斥效果呢? 在使用Qt做一个界面美观性比较强的功能时,可能会遇到这种问题:多个控件互斥,类似于QRadiButton控件,但又不是单纯的QRadioButton控件,互斥的可能是一个窗口,也可能是几个按钮,等等多种情况. 这里我只是列举了一个简单的互斥例子,虽然简单,但是包含了各种坑,有需要的掘友们可以小笔记们记一下,尤其是对Qt新手来说,还是很有必要的. 由效果图可以看出创

  • javascript+html5+css3自定义弹出窗口效果

    本文实例为大家分享了js自定义弹出窗口效果展示的具体代码,供大家参考,具体内容如下 效果图: 源码: 1.demo.jsp <%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>自定义弹出窗口</title> <script type="text/javascript&qu

  • js实现YouKu的漂亮搜索框效果

    本文实例讲述了js实现YouKu的漂亮搜索框效果.分享给大家供大家参考.具体如下: 运行效果如下图所示: 在线演示地址如下: http://demo.jb51.net/js/2015/js-youku-search-style-codes/ 具体代码如下: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-trans

  • iOS自定义collectionView实现毛玻璃效果

    先来看看效果图,由于录屏软件不给力,毛玻璃效果不明显,请见谅. 步骤详解: 说下思路,很简单,首先自定义一个collectionView, 重写它的initWithFrame:collectionViewLayout:方法,在这里面做配置,这里用的是AXECollectionView. 与之对应的自定义一个collectionViewCell,在cell里配置操作:设置layer涂层,加载图片等操作,这里用的是AXECollectionViewCell. 最后在需要展示的控制器里调用AXECol

  • jQuery实现的自定义弹出层效果实例详解

    本文实例讲述了jQuery实现的自定义弹出层效果.分享给大家供大家参考,具体如下: dialog.css: #DialogBySHFLayer { width:100%; height:100%; left:0; top:0; position:fixed; z-index:500; background-color:#333333; filter:alpha(Opacity=40); -moz-opacity:0.4; opacity: 0.4; } /*弹出的提示框*/ #DialogByS

  • jquery mobile 实现自定义confirm确认框效果的简单实例

    类似删除的效果,在执行之前,一般需要添加确认对话框,点确认的话执行,取消按钮就不执行,传统的js if(confirm('确定删除吗?')) { //执行代码 } 这种效果比较丑,使用jquery mobile优化一下 需要引用的文件: <script src="~/Scripts/jquery-1.10.2.min.js"></script> <link href="~/Scripts/Mobile/jquery.mobile-1.4.0.mi

随机推荐