這篇“C# Winform如何實現自定義漂亮的通知效果”文章的知識點大部分人都不太理解,所以小編給大家總結了以下內容,內容詳細,步驟清晰,具有一定的借鑒價值,希望大家閱讀完這篇文章能有所收獲,下面我們一起來看看這篇“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個通知框,當再多時不會顯示(丟失掉),只有騰出位置(通知消失后)才能顯示新的,現在已經優化為超出的通知框會替換掉舊通知,不會丟失。
// 設置通知的數量 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如何實現自定義漂亮的通知效果”這篇文章的內容,相信大家都有了一定的了解,希望小編分享的內容對大家有幫助,若想了解更多相關的知識內容,請關注億速云行業資訊頻道。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。