基於.Net4.0實現 ToastNotification
Windows更新之路的特色之一就是消息提示由氣泡變成了通知窗口,效果簡直不要太好。最近公司有這方面的需求,需要在xp,win7系統上給出提示,由此做了一個仿win10的ToastNotification,給出代碼供大家參考:
開源庫中也有很多的ToastNotification實現,但是我發現幾乎都是基於一個應用的:當你打開一個應用,彈出的界面會向上堆疊,但是當你打開多個應用程序,彈出的界面會重疊在一起。后來通過共享內存文件的方式使他們互相通知我已經畫到哪里了(主要是沒用過進程間通訊,學習一下,哈哈)
效果圖:
支持
·WPF
·WINFORM
·控制台程序
·顯示界面可自定義
·自由控制動畫
原理:
原理非常簡單:
消息界面是wpf窗口,在窗口的Loaded和Closing事件添加滑入滑出動畫:
view.Loaded += OverrideLoaded;
view.ShowInTaskbar = false;
if (!view.Options.IsAutoClose)
{
view.Closing += OverrideClosing;
}
Loaded函數中的動畫
animation.Duration = notifier.Options.AnamitionDurationTime;
animation.From = notifier.Options.RightFrom;
animation.To = notifier.Options.RightTo;
notifier.BeginAnimation(Window.LeftProperty, animation);
if (notifier.Options.IsAutoClose)
{
Task.Factory.StartNew(delegate
{
int seconds = notifier.Options.AutoCloseShowTimeMS;
System.Threading.Thread.Sleep(TimeSpan.FromMilliseconds(seconds));
notifier.Dispatcher.Invoke(new Action(() =>
{
{
animation = new DoubleAnimation();
animation.Duration = notifier.Options.AnamitionDurationTime;
animation.Completed += (s, a) =>
{
notifier.CloseFun();
};
animation.From = notifier.Options.RightTo;
animation.To = notifier.Options.RightFrom;
notifier.BeginAnimation(Window.LeftProperty, animation);
}
}));
});
}
Closing
DoubleAnimation animation = new DoubleAnimation();
animation.Duration = notifier.Options.AnamitionDurationTime;
animation.Completed += (s, a) => { notifier.Closing -= OverrideClosing;};
animation.From = notifier.Options.RightTo;
animation.To = notifier.Options.RightFrom;
notifier.BeginAnimation(Window.LeftProperty, animation);
需要注意的是在控制台程序中,由於沒有消息循環,你需要將窗口Showdialog()
(大約是這樣,類似於控制台程序的App.Run(window)沒有消息循環而無法通知)
用法:
封裝了幾個接口,可以直接用,效果如效果圖:
private void ButtonWarn_Click(object sender, RoutedEventArgs e)
{
Notifier.ShowWarn(Header.Text, GetString(), IsAutoClose.IsChecked == null ? false : (bool)IsAutoClose.IsChecked, int.Parse(Time.Text));
}
private void ButtonSuccess_Click(object sender, RoutedEventArgs e)
{
Notifier.ShowSuccess(Header.Text, GetString(), IsAutoClose.IsChecked == null ? false : (bool)IsAutoClose.IsChecked, int.Parse(Time.Text));
}
private void ButtonError_Click(object sender, RoutedEventArgs e)
{
Notifier.ShowError(Header.Text, GetString(), IsAutoClose.IsChecked == null ? false : (bool)IsAutoClose.IsChecked, int.Parse(Time.Text));
}
自定義窗口只需要繼承NotifierViewBase,設計好樣式就好了,然后調用Notifier.ShowView(NotifierViewBase view, ShowOptions options)
<baseView:NotifierViewBase x:Class="ToastNotification_Demo.CuttomView"
xmlns:baseView="clr-namespace:ToastNotification.Base;assembly=ToastNotification"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:ToastNotification_Demo"
mc:Ignorable="d"
Height="150" Width="500" Topmost="True" AllowsTransparency="True" Background="Transparent" WindowStyle="None">
<Grid>
<Label FontSize="72">Custom View</Label>
</Grid>
</baseView:NotifierViewBase>
介紹一下ShowOptions 類,里面主要是動畫效果的屬性,可以ShowView的時候傳進去:
/// <summary>
/// 是否播放提示音
/// </summary>
public bool IsEnabledSounds { get; set; } = true;
/// <summary>
/// 是否自動關閉
/// </summary>
public bool IsAutoClose { get; set; } = true;
/// <summary>
/// 配合IsAutoClose,window顯示時間
/// </summary>
public int AutoCloseShowTimeMS { get; set; } = 5000;
/// <summary>
/// 窗口顯示位置(一般情況下不需要設置)
/// </summary>
public double NotifierTop { get; set; } = double.NaN;
/// <summary>
/// 窗口顯示位置(動畫初始位置)(一般情況下不需要設置)
/// </summary>
public double RightFrom { get; set; } = double.NaN;
/// <summary>
/// 窗口顯示位置(動畫結束位置)(一般情況下不需要設置)
/// </summary>
public double RightTo { get; set; } = double.NaN;
/// <summary>
/// 動畫執行時間
/// </summary>
public Duration AnamitionDurationTime { get; set; } = new Duration(TimeSpan.FromMilliseconds(500));
/// <summary>
/// 是否是固定大小(W:300 h:150),否則為自適應大小
/// </summary>
public bool IsFixedSizeOrContentToWH { get; set; } = true;
/// <summary>
/// FixedSize時的高度,默認150
/// </summary>
public Double Height { get; set; } = 150;
/// <summary>
/// FixedSize時的寬度,默認350
/// </summary>
public Double Width { get; set; } = 350;
Github code+Sample地址: