Toasts – Rev 17
?pathlinks?
// =====COPYRIGHT=====
// Code originally retrieved from http://www.vbforums.com/showthread.php?t=547778 - no license information supplied
// =====COPYRIGHT=====
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Diagnostics;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Media;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
using Toasts.Properties;
namespace Toasts
{
public partial class ToastForm : Form
{
#region Static Fields and Constants
private static readonly object OpenNotificationsLock = new object();
private static readonly HashSet<ToastForm> OpenNotifications = new HashSet<ToastForm>();
#endregion
#region Private Overrides
protected override bool ShowWithoutActivation => true;
protected override CreateParams CreateParams
{
get
{
var baseParams = base.CreateParams;
const int WS_EX_NOACTIVATE = 0x08000000;
const int WS_EX_TOOLWINDOW = 0x00000080;
const int WS_EX_TOPMOST = 0x00000008;
baseParams.ExStyle |= WS_EX_NOACTIVATE | WS_EX_TOOLWINDOW | WS_EX_TOPMOST;
return baseParams;
}
}
#endregion
#region Constructors, Destructors and Finalizers
private ToastForm()
{
InitializeComponent();
Region = Region.FromHrgn(NativeMethods.CreateRoundRectRgn(0, 0, Width - 5, Height - 5, 20, 20));
_screenWidth = Screen.PrimaryScreen.WorkingArea.Width;
_screenHeight = Screen.PrimaryScreen.WorkingArea.Height;
_formAnimator = new FormAnimator(this, FormAnimator.AnimationMethod.Slide, FormAnimator.AnimationDirection.Up,
500);
using (var memoryStream = new MemoryStream())
{
Resources.normal.CopyTo(memoryStream);
memoryStream.Position = 0L;
_sound = memoryStream.ToArray();
}
_toastTimer = new System.Timers.Timer();
_toastTimer.Elapsed += ToastTimer_Elapsed;
_toastTimer.Enabled = false;
}
/// <summary>
/// Display a toast with a title, body and a logo indefinitely on screen.
/// </summary>
/// <param name="title">the toast title</param>
/// <param name="body">the toast body</param>
/// <param name="logo">the toast logo</param>
public ToastForm(string title, string body, Image logo) : this()
{
_toastTimer.Enabled = false;
labelTitle.Text = title;
labelBody.Text = body;
imageBox.Image = logo;
}
/// <summary>
/// Display a toast on screen.
/// </summary>
/// <param name="title">the toast title</param>
/// <param name="body">the toast body</param>
/// <param name="duration">the duration in milliseconds to display the toast on screen for</param>
/// <param name="logo">the toast logo</param>
/// <param name="background">the background image for the toast</param>
/// <param name="sound">a sound to play when the toast is displayed</param>
/// <param name="animation">the form animation type <see cref="FormAnimator"/></param>
/// <param name="direction">the form animation direction <see cref="FormAnimator"/></param>
public ToastForm(string title, string body, int duration, Image logo, Image background, byte[] sound,
FormAnimator.AnimationMethod animation, FormAnimator.AnimationDirection direction) : this()
{
_toastTimer.Enabled = true;
_toastTimer.Interval = duration;
labelTitle.Text = title;
labelBody.Text = body;
imageBox.Image = logo;
BackgroundImage = background;
_sound = sound;
_formAnimator = new FormAnimator(this, animation, direction, 500);
}
/// <summary>
/// Display a toast on screen.
/// </summary>
/// <param name="title">the toast title</param>
/// <param name="body">the toast body</param>
/// <param name="duration">the duration in milliseconds to display the toast on screen for</param>
/// <param name="logo">the toast logo</param>
/// <param name="sound">a sound to play when the toast is displayed</param>
/// <param name="animation">the form animation type <see cref="FormAnimator"/></param>
/// <param name="direction">the form animation direction <see cref="FormAnimator"/></param>
public ToastForm(string title, string body, int duration, Image logo, byte[] sound,
FormAnimator.AnimationMethod animation, FormAnimator.AnimationDirection direction) : this()
{
_toastTimer.Enabled = true;
_toastTimer.Interval = duration;
labelTitle.Text = title;
labelBody.Text = body;
imageBox.Image = logo;
_sound = sound;
_formAnimator = new FormAnimator(this, animation, direction, 500);
}
/// <summary>
/// Display a toast on screen.
/// </summary>
/// <param name="title">the toast title</param>
/// <param name="body">the toast body</param>
/// <param name="duration">the duration in milliseconds to display the toast on screen for</param>
/// <param name="logo">the toast logo</param>
/// <param name="sound">a sound to play when the toast is displayed</param>
public ToastForm(string title, string body, int duration, Image logo, byte[] sound) : this()
{
_toastTimer.Enabled = true;
_toastTimer.Interval = duration;
labelTitle.Text = title;
labelBody.Text = body;
imageBox.Image = logo;
_sound = sound;
}
/// <summary>
/// Display a toast on screen.
/// </summary>
/// <param name="title">the toast title</param>
/// <param name="body">the toast body</param>
/// <param name="duration">the duration in milliseconds to display the toast on screen for</param>
/// <param name="logo">the toast logo</param>
public ToastForm(string title, string body, int duration, Image logo) : this()
{
_toastTimer.Enabled = true;
_toastTimer.Interval = duration;
labelTitle.Text = title;
labelBody.Text = body;
imageBox.Image = logo;
}
/// <summary>
/// Display a toast on screen.
/// </summary>
/// <param name="title">the toast title</param>
/// <param name="body">the toast body</param>
/// <param name="duration">the duration in milliseconds to display the toast on screen for</param>
/// <param name="logo">the toast logo</param>
public ToastForm(string title, string body, int duration, Icon logo) : this()
{
_toastTimer.Interval = duration;
labelTitle.Text = title;
labelBody.Text = body;
imageBox.Image = logo.ToBitmap();
}
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && components != null)
{
if (_toastTimer != null)
{
_toastTimer.Dispose();
_toastTimer = null;
}
components.Dispose();
}
base.Dispose(disposing);
}
#endregion
#region Private Delegates, Events, Enums, Properties, Indexers and Fields
private readonly FormAnimator _formAnimator;
private readonly byte[] _sound;
private System.Timers.Timer _toastTimer;
private readonly int _screenWidth;
private readonly int _screenHeight;
#endregion
#region Event Handlers
private void Notification_Load(object sender, EventArgs e)
{
Task.Factory.StartNew(() =>
{
using (var memoryStream = new MemoryStream(_sound))
{
using (var player = new SoundPlayer(memoryStream))
{
player.Play();
}
}
});
try
{
lock (OpenNotificationsLock)
{
var notifications = OpenNotifications.ToArray();
foreach (var openForm in notifications)
{
if (openForm == null)
{
continue;
}
if (openForm.IsDisposed)
{
OpenNotifications.Remove(openForm);
continue;
}
if (openForm.IsHandleCreated != true)
{
continue;
}
// Move each open form upwards to make room for this one
var handle = Handle;
openForm.BeginInvoke(new MethodInvoker(() =>
{
try
{
if (openForm.Handle == handle)
{
return;
}
openForm.Top -= Height;
}
catch
{
Debug.WriteLine("Error while moving forms up.");
}
}));
}
Invoke(new MethodInvoker(() =>
{
Location = new Point(_screenWidth - Width, _screenHeight - Height);
}));
OpenNotifications.Add(this);
// Only start the timer if it has been enabled in the constructor.
if (_toastTimer.Enabled)
{
_toastTimer.Start();
}
}
}
catch
{
Debug.WriteLine("Error on form load event.");
}
}
private void Notification_FormClosed(object sender, FormClosedEventArgs e)
{
try
{
lock (OpenNotificationsLock)
{
OpenNotifications.Remove(this);
}
}
catch
{
Debug.WriteLine("Error in form closed event.");
}
}
private void Notification_Shown(object sender, EventArgs e)
{
// Reverse animation direction for hiding.
switch (_formAnimator.Direction)
{
case FormAnimator.AnimationDirection.Up:
_formAnimator.Direction = FormAnimator.AnimationDirection.Down;
break;
case FormAnimator.AnimationDirection.Down:
_formAnimator.Direction = FormAnimator.AnimationDirection.Up;
break;
case FormAnimator.AnimationDirection.Left:
_formAnimator.Direction = FormAnimator.AnimationDirection.Right;
break;
case FormAnimator.AnimationDirection.Right:
_formAnimator.Direction = FormAnimator.AnimationDirection.Left;
break;
}
}
private void ToastTimer_Elapsed(object sender, EventArgs e)
{
if (IsDisposed)
{
return;
}
try
{
_toastTimer.Stop();
BeginInvoke(new MethodInvoker(() =>
{
lock (OpenNotificationsLock)
{
Close();
}
}));
}
catch
{
Debug.WriteLine("Error in timer elapsed event.");
}
}
private void Toast_Click(object sender, EventArgs e)
{
try
{
lock (OpenNotificationsLock)
{
Close();
}
}
catch
{
Debug.WriteLine("Error in form click event.");
}
}
#endregion
}
}
Generated by GNU Enscript 1.6.5.90.