Toasts – Blame information for rev 15

Subversion Repositories:
Rev:
Rev Author Line No. Line
1 office 1 // =====COPYRIGHT=====
2 // Code originally retrieved from http://www.vbforums.com/showthread.php?t=547778 - no license information supplied
3 // =====COPYRIGHT=====
4  
5 using System;
15 office 6 using System.Collections.Concurrent;
1 office 7 using System.Drawing;
8 office 8 using System.IO;
15 office 9 using System.Linq;
8 office 10 using System.Media;
1 office 11 using System.Windows.Forms;
11 office 12 using Toasts.Properties;
1 office 13  
14 namespace Toasts
15 {
2 office 16 public partial class ToastForm : Form
1 office 17 {
18 #region Static Fields and Constants
19  
15 office 20 private static readonly ConcurrentDictionary<IntPtr, ToastForm> OpenNotifications = new ConcurrentDictionary<IntPtr, ToastForm>();
1 office 21  
22 #endregion
23  
12 office 24 #region Private Overrides
25  
26 protected override bool ShowWithoutActivation => true;
27  
28 protected override CreateParams CreateParams
29 {
30 get
31 {
32 var baseParams = base.CreateParams;
33  
34 const int WS_EX_NOACTIVATE = 0x08000000;
35 const int WS_EX_TOOLWINDOW = 0x00000080;
36 const int WS_EX_TOPMOST = 0x00000008;
37 baseParams.ExStyle |= WS_EX_NOACTIVATE | WS_EX_TOOLWINDOW | WS_EX_TOPMOST;
38  
39 return baseParams;
40 }
41 }
42  
43 #endregion
44  
1 office 45 #region Constructors, Destructors and Finalizers
46  
11 office 47 private ToastForm()
7 office 48 {
49 InitializeComponent();
15 office 50  
51 foreach (var control in Controls.Cast<Control>())
52 {
53 control.Click += Toast_Click;
54 }
55  
56 Click += Toast_Click;
57  
58 _toastTimer = new System.Timers.Timer();
59 _toastTimer.Elapsed += ToastTimer_Elapsed;
60 _toastTimer.Enabled = false;
7 office 61 }
11 office 62  
1 office 63 /// <summary>
15 office 64 /// Display a toast with a title, body and a logo indefinitely on screen.
1 office 65 /// </summary>
15 office 66 /// <param name="title">the toast title</param>
67 /// <param name="body">the toast body</param>
68 /// <param name="logo">the toast logo</param>
69 public ToastForm(string title, string body, Image logo) : this()
70 {
71 _toastTimer.Enabled = false;
72 labelTitle.Text = title;
73 labelBody.Text = body;
74 imageBox.Image = logo;
75  
76 _animator = new FormAnimator(this, FormAnimator.AnimationMethod.Slide, FormAnimator.AnimationDirection.Up,
77 500);
78  
79 Region = Region.FromHrgn(NativeMethods.CreateRoundRectRgn(0, 0, Width - 5, Height - 5, 20, 20));
80 }
81  
82 /// <summary>
83 /// Display a toast on screen.
84 /// </summary>
85 /// <param name="title">the toast title</param>
86 /// <param name="body">the toast body</param>
87 /// <param name="duration">the duration in milliseconds to display the toast on screen for</param>
88 /// <param name="logo">the toast logo</param>
89 /// <param name="background">the background image for the toast</param>
90 /// <param name="sound">a sound to play when the toast is displayed</param>
91 /// <param name="animation">the form animation type <see cref="FormAnimator"/></param>
92 /// <param name="direction">the form animation direction <see cref="FormAnimator"/></param>
8 office 93 public ToastForm(string title, string body, int duration, Image logo, Image background, byte[] sound,
7 office 94 FormAnimator.AnimationMethod animation, FormAnimator.AnimationDirection direction) : this()
1 office 95 {
15 office 96 _toastTimer.Enabled = true;
97 _toastTimer.Interval = duration;
1 office 98 labelTitle.Text = title;
99 labelBody.Text = body;
100 imageBox.Image = logo;
101 BackgroundImage = background;
102  
8 office 103 _sound = sound;
104  
1 office 105 _animator = new FormAnimator(this, animation, direction, 500);
106  
107 Region = Region.FromHrgn(NativeMethods.CreateRoundRectRgn(0, 0, Width - 5, Height - 5, 20, 20));
108 }
109  
15 office 110 /// <summary>
111 /// Display a toast on screen.
112 /// </summary>
113 /// <param name="title">the toast title</param>
114 /// <param name="body">the toast body</param>
115 /// <param name="duration">the duration in milliseconds to display the toast on screen for</param>
116 /// <param name="logo">the toast logo</param>
117 /// <param name="sound">a sound to play when the toast is displayed</param>
118 /// <param name="animation">the form animation type <see cref="FormAnimator"/></param>
119 /// <param name="direction">the form animation direction <see cref="FormAnimator"/></param>
8 office 120 public ToastForm(string title, string body, int duration, Image logo, byte[] sound,
7 office 121 FormAnimator.AnimationMethod animation, FormAnimator.AnimationDirection direction) : this()
2 office 122 {
15 office 123 _toastTimer.Enabled = true;
124 _toastTimer.Interval = duration;
2 office 125 labelTitle.Text = title;
126 labelBody.Text = body;
127 imageBox.Image = logo;
1 office 128  
8 office 129 _sound = sound;
130  
2 office 131 _animator = new FormAnimator(this, animation, direction, 500);
132  
133 Region = Region.FromHrgn(NativeMethods.CreateRoundRectRgn(0, 0, Width - 5, Height - 5, 20, 20));
134 }
135  
15 office 136 /// <summary>
137 /// Display a toast on screen.
138 /// </summary>
139 /// <param name="title">the toast title</param>
140 /// <param name="body">the toast body</param>
141 /// <param name="duration">the duration in milliseconds to display the toast on screen for</param>
142 /// <param name="logo">the toast logo</param>
143 /// <param name="sound">a sound to play when the toast is displayed</param>
8 office 144 public ToastForm(string title, string body, int duration, Image logo, byte[] sound) : this()
1 office 145 {
15 office 146 _toastTimer.Enabled = true;
147 _toastTimer.Interval = duration;
2 office 148 labelTitle.Text = title;
149 labelBody.Text = body;
150 imageBox.Image = logo;
151  
8 office 152 _sound = sound;
153  
2 office 154 _animator = new FormAnimator(this, FormAnimator.AnimationMethod.Slide, FormAnimator.AnimationDirection.Up,
155 500);
156  
157 Region = Region.FromHrgn(NativeMethods.CreateRoundRectRgn(0, 0, Width - 5, Height - 5, 20, 20));
1 office 158 }
159  
15 office 160 /// <summary>
161 /// Display a toast on screen.
162 /// </summary>
163 /// <param name="title">the toast title</param>
164 /// <param name="body">the toast body</param>
165 /// <param name="duration">the duration in milliseconds to display the toast on screen for</param>
166 /// <param name="logo">the toast logo</param>
9 office 167 public ToastForm(string title, string body, int duration, Image logo) : this()
168 {
15 office 169 _toastTimer.Enabled = true;
170 _toastTimer.Interval = duration;
9 office 171 labelTitle.Text = title;
172 labelBody.Text = body;
173 imageBox.Image = logo;
174  
175 _animator = new FormAnimator(this, FormAnimator.AnimationMethod.Slide, FormAnimator.AnimationDirection.Up,
176 500);
177  
178 Region = Region.FromHrgn(NativeMethods.CreateRoundRectRgn(0, 0, Width - 5, Height - 5, 20, 20));
179 }
180  
15 office 181 /// <summary>
182 /// Display a toast on screen.
183 /// </summary>
184 /// <param name="title">the toast title</param>
185 /// <param name="body">the toast body</param>
186 /// <param name="duration">the duration in milliseconds to display the toast on screen for</param>
187 /// <param name="logo">the toast logo</param>
10 office 188 public ToastForm(string title, string body, int duration, Icon logo) : this()
189 {
15 office 190 _toastTimer.Interval = duration;
10 office 191 labelTitle.Text = title;
192 labelBody.Text = body;
193 imageBox.Image = logo.ToBitmap();
194  
195 _animator = new FormAnimator(this, FormAnimator.AnimationMethod.Slide, FormAnimator.AnimationDirection.Up,
196 500);
197  
198 Region = Region.FromHrgn(NativeMethods.CreateRoundRectRgn(0, 0, Width - 5, Height - 5, 20, 20));
199 }
200  
7 office 201 /// <summary>
11 office 202 /// Clean up any resources being used.
7 office 203 /// </summary>
204 /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
205 protected override void Dispose(bool disposing)
206 {
11 office 207 if (disposing && components != null) components.Dispose();
7 office 208 base.Dispose(disposing);
209 }
210  
1 office 211 #endregion
212  
213 #region Private Delegates, Events, Enums, Properties, Indexers and Fields
214  
215 private readonly FormAnimator _animator;
216  
15 office 217 private byte[] _sound;
1 office 218  
15 office 219 private readonly System.Timers.Timer _toastTimer;
1 office 220  
221 #endregion
222  
223 #region Event Handlers
224  
9 office 225 private void Notification_Load(object sender, EventArgs e)
1 office 226 {
8 office 227 // Play the sound.
228 if (_sound == null)
9 office 229 using (var memoryStream = new MemoryStream())
230 {
11 office 231 Resources.normal.CopyTo(memoryStream);
9 office 232  
233 memoryStream.Position = 0L;
234  
235 _sound = memoryStream.ToArray();
236 }
8 office 237  
238 using (var memoryStream = new MemoryStream(_sound))
239 {
240 using (var player = new SoundPlayer(memoryStream))
241 {
242 player.Play();
243 }
244 }
245  
1 office 246 // Move each open form upwards to make room for this one
15 office 247 foreach (var openForm in OpenNotifications.Values)
4 office 248 {
249 if (openForm.InvokeRequired)
250 {
15 office 251 void Move()
252 {
253 openForm.Top -= Height;
254 }
7 office 255  
15 office 256 openForm.Invoke((Action)Move);
257  
7 office 258 continue;
4 office 259 }
1 office 260  
4 office 261 openForm.Top -= Height;
262 }
263  
15 office 264 // Display the form just above the system tray.
265 Location = new Point(Screen.PrimaryScreen.WorkingArea.Width - Width,
266 Screen.PrimaryScreen.WorkingArea.Height - Height);
1 office 267  
15 office 268 OpenNotifications.TryAdd(Handle, this);
269  
270 // Only start the timer if it has been enabled in the constructor.
271 if (_toastTimer.Enabled)
272 {
273 _toastTimer.Start();
274 }
1 office 275 }
276  
277 private void Notification_Shown(object sender, EventArgs e)
278 {
279 // Close the form by sliding down.
280 _animator.Duration = 0;
281 _animator.Direction = FormAnimator.AnimationDirection.Down;
282 }
283  
284 private void Notification_FormClosed(object sender, FormClosedEventArgs e)
285 {
286 // Move down any open forms above this one
15 office 287 foreach (var openForm in OpenNotifications.Values)
1 office 288 {
15 office 289 if (openForm.Handle == Handle)
290 continue;
1 office 291  
7 office 292 if (openForm.InvokeRequired)
293 {
15 office 294 void Move()
295 {
296 openForm.Top += Height;
297 }
298  
299 openForm.Invoke((Action)Move);
300  
301 continue;
7 office 302 }
15 office 303  
304 openForm.Top += Height;
1 office 305 }
306  
15 office 307 OpenNotifications.TryRemove(Handle, out _);
1 office 308 }
309  
15 office 310 private void ToastTimer_Elapsed(object sender, EventArgs e)
1 office 311 {
15 office 312 if (InvokeRequired)
313 {
314 BeginInvoke(new MethodInvoker(Close));
1 office 315  
15 office 316 return;
317 }
1 office 318  
319 Close();
320 }
321  
15 office 322 private void Toast_Click(object sender, EventArgs e)
1 office 323 {
324 Close();
325 }
326  
327 #endregion
328 }
329 }