Toasts – Rev 8
?pathlinks?
// =====COPYRIGHT=====
// Code originally retrieved from http://www.vbforums.com/showthread.php?t=547778 - no license information supplied
// =====COPYRIGHT=====
using System;
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using System.Media;
using System.Reflection;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace Toasts
{
public partial class ToastForm : Form
{
#region Static Fields and Constants
private static readonly List<ToastForm> OpenNotifications = new List<ToastForm>();
#endregion
#region Public Methods
/// <summary>
/// Displays the form
/// </summary>
/// <remarks>
/// Required to allow the form to determine the current foreground window before being displayed
/// </remarks>
public new void Show()
{
// Determine the current foreground window so it can be reactivated each time this form tries to get the focus
_currentForegroundWindow = NativeMethods.GetForegroundWindow();
base.Show();
}
#endregion
#region Private Methods
private static async Task<byte[]> LoadResource(string resource)
{
var assembly = Assembly.GetExecutingAssembly();
using (var manifestResourceStream = assembly.GetManifestResourceStream(resource))
{
if (manifestResourceStream == null)
{
return null;
}
var memoryStream = new MemoryStream();
await manifestResourceStream.CopyToAsync(memoryStream);
memoryStream.Position = 0L;
return memoryStream.ToArray();
}
}
#endregion
#region Constructors, Destructors and Finalizers
private ToastForm()
{
InitializeComponent();
}
/// <summary>
/// </summary>
/// <param name="title"></param>
/// <param name="body"></param>
/// <param name="duration"></param>
/// <param name="image"></param>
/// <param name="animation"></param>
/// <param name="direction"></param>
public ToastForm(string title, string body, int duration, Image logo, Image background, byte[] sound,
FormAnimator.AnimationMethod animation, FormAnimator.AnimationDirection direction) : this()
{
lifeTimer.Interval = duration;
labelTitle.Text = title;
labelBody.Text = body;
imageBox.Image = logo;
BackgroundImage = background;
_sound = sound;
_animator = new FormAnimator(this, animation, direction, 500);
Region = Region.FromHrgn(NativeMethods.CreateRoundRectRgn(0, 0, Width - 5, Height - 5, 20, 20));
}
public ToastForm(string title, string body, int duration, Image logo, byte[] sound,
FormAnimator.AnimationMethod animation, FormAnimator.AnimationDirection direction) : this()
{
lifeTimer.Interval = duration;
labelTitle.Text = title;
labelBody.Text = body;
imageBox.Image = logo;
_sound = sound;
_animator = new FormAnimator(this, animation, direction, 500);
Region = Region.FromHrgn(NativeMethods.CreateRoundRectRgn(0, 0, Width - 5, Height - 5, 20, 20));
}
public ToastForm(string title, string body, int duration, Image logo, byte[] sound) : this()
{
lifeTimer.Interval = duration;
labelTitle.Text = title;
labelBody.Text = body;
imageBox.Image = logo;
_sound = sound;
_animator = new FormAnimator(this, FormAnimator.AnimationMethod.Slide, FormAnimator.AnimationDirection.Up,
500);
Region = Region.FromHrgn(NativeMethods.CreateRoundRectRgn(0, 0, Width - 5, Height - 5, 20, 20));
}
/// <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))
{
components.Dispose();
}
base.Dispose(disposing);
}
#endregion
#region Private Delegates, Events, Enums, Properties, Indexers and Fields
private readonly FormAnimator _animator;
private bool _allowFocus;
private IntPtr _currentForegroundWindow;
private byte[] _sound;
#endregion
#region Event Handlers
private async void Notification_Load(object sender, EventArgs e)
{
// Play the sound.
if (_sound == null)
{
_sound = await LoadResource($"Toasts.Sounds.default.wav");
}
using (var memoryStream = new MemoryStream(_sound))
{
using (var player = new SoundPlayer(memoryStream))
{
player.Play();
}
}
// Display the form just above the system tray.
Location = new Point(Screen.PrimaryScreen.WorkingArea.Width - Width,
Screen.PrimaryScreen.WorkingArea.Height - Height);
// Move each open form upwards to make room for this one
foreach (var openForm in OpenNotifications)
{
if (openForm.InvokeRequired)
{
Action action = delegate { openForm.Top -= Height; };
openForm.Invoke(action);
continue;
}
openForm.Top -= Height;
}
OpenNotifications.Add(this);
lifeTimer.Start();
}
private void Notification_Activated(object sender, EventArgs e)
{
// Prevent the form taking focus when it is initially shown
if (!_allowFocus)
{
// Activate the window that previously had focus
NativeMethods.SetForegroundWindow(_currentForegroundWindow);
}
}
private void Notification_Shown(object sender, EventArgs e)
{
// Once the animation has completed the form can receive focus
_allowFocus = true;
// Close the form by sliding down.
_animator.Duration = 0;
_animator.Direction = FormAnimator.AnimationDirection.Down;
}
private void Notification_FormClosed(object sender, FormClosedEventArgs e)
{
// Move down any open forms above this one
foreach (var openForm in OpenNotifications)
{
if (openForm == this)
// Remaining forms are below this one
break;
if (openForm.InvokeRequired)
{
Action action = delegate { openForm.Top += Height; };
openForm.Invoke(action);
continue;
}
}
OpenNotifications.Remove(this);
}
private void LifeTimer_Tick(object sender, EventArgs e)
{
Close();
}
private void Notification_Click(object sender, EventArgs e)
{
Close();
}
private void LabelTitle_Click(object sender, EventArgs e)
{
Close();
}
private void LabelRO_Click(object sender, EventArgs e)
{
Close();
}
#endregion
}
}
Generated by GNU Enscript 1.6.5.90.