Toasts – Blame information for rev 16

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;
16 office 7 using System.Collections.Generic;
8 using System.Diagnostics;
1 office 9 using System.Drawing;
8 office 10 using System.IO;
15 office 11 using System.Linq;
8 office 12 using System.Media;
16 office 13 using System.Threading;
14 using System.Threading.Tasks;
1 office 15 using System.Windows.Forms;
11 office 16 using Toasts.Properties;
1 office 17  
18 namespace Toasts
19 {
2 office 20 public partial class ToastForm : Form
1 office 21 {
22 #region Static Fields and Constants
23  
16 office 24 private static readonly object OpenNotificationsLock = new object();
1 office 25  
16 office 26 private static readonly HashSet<ToastForm> OpenNotifications = new HashSet<ToastForm>();
27  
1 office 28 #endregion
29  
12 office 30 #region Private Overrides
31  
32 protected override bool ShowWithoutActivation => true;
33  
34 protected override CreateParams CreateParams
35 {
36 get
37 {
38 var baseParams = base.CreateParams;
39  
40 const int WS_EX_NOACTIVATE = 0x08000000;
41 const int WS_EX_TOOLWINDOW = 0x00000080;
42 const int WS_EX_TOPMOST = 0x00000008;
43 baseParams.ExStyle |= WS_EX_NOACTIVATE | WS_EX_TOOLWINDOW | WS_EX_TOPMOST;
44  
45 return baseParams;
46 }
47 }
48  
49 #endregion
50  
1 office 51 #region Constructors, Destructors and Finalizers
52  
11 office 53 private ToastForm()
7 office 54 {
55 InitializeComponent();
16 office 56 Region = Region.FromHrgn(NativeMethods.CreateRoundRectRgn(0, 0, Width - 5, Height - 5, 20, 20));
57  
58 _screenWidth = Screen.PrimaryScreen.WorkingArea.Width;
59 _screenHeight = Screen.PrimaryScreen.WorkingArea.Height;
15 office 60  
16 office 61 _formAnimator = new FormAnimator(this, FormAnimator.AnimationMethod.Slide, FormAnimator.AnimationDirection.Up,
62 500);
63  
64 using (var memoryStream = new MemoryStream())
15 office 65 {
16 office 66 Resources.normal.CopyTo(memoryStream);
67  
68 memoryStream.Position = 0L;
69  
70 _sound = memoryStream.ToArray();
15 office 71 }
72  
73 _toastTimer = new System.Timers.Timer();
74 _toastTimer.Elapsed += ToastTimer_Elapsed;
75 _toastTimer.Enabled = false;
7 office 76 }
11 office 77  
1 office 78 /// <summary>
15 office 79 /// Display a toast with a title, body and a logo indefinitely on screen.
1 office 80 /// </summary>
15 office 81 /// <param name="title">the toast title</param>
82 /// <param name="body">the toast body</param>
83 /// <param name="logo">the toast logo</param>
84 public ToastForm(string title, string body, Image logo) : this()
85 {
86 _toastTimer.Enabled = false;
87 labelTitle.Text = title;
88 labelBody.Text = body;
89 imageBox.Image = logo;
90 }
91  
92 /// <summary>
93 /// Display a toast on screen.
94 /// </summary>
95 /// <param name="title">the toast title</param>
96 /// <param name="body">the toast body</param>
97 /// <param name="duration">the duration in milliseconds to display the toast on screen for</param>
98 /// <param name="logo">the toast logo</param>
99 /// <param name="background">the background image for the toast</param>
100 /// <param name="sound">a sound to play when the toast is displayed</param>
101 /// <param name="animation">the form animation type <see cref="FormAnimator"/></param>
102 /// <param name="direction">the form animation direction <see cref="FormAnimator"/></param>
8 office 103 public ToastForm(string title, string body, int duration, Image logo, Image background, byte[] sound,
7 office 104 FormAnimator.AnimationMethod animation, FormAnimator.AnimationDirection direction) : this()
1 office 105 {
15 office 106 _toastTimer.Enabled = true;
107 _toastTimer.Interval = duration;
1 office 108 labelTitle.Text = title;
109 labelBody.Text = body;
110 imageBox.Image = logo;
111 BackgroundImage = background;
112  
8 office 113 _sound = sound;
114  
16 office 115 _formAnimator = new FormAnimator(this, animation, direction, 500);
1 office 116 }
117  
15 office 118 /// <summary>
119 /// Display a toast on screen.
120 /// </summary>
121 /// <param name="title">the toast title</param>
122 /// <param name="body">the toast body</param>
123 /// <param name="duration">the duration in milliseconds to display the toast on screen for</param>
124 /// <param name="logo">the toast logo</param>
125 /// <param name="sound">a sound to play when the toast is displayed</param>
126 /// <param name="animation">the form animation type <see cref="FormAnimator"/></param>
127 /// <param name="direction">the form animation direction <see cref="FormAnimator"/></param>
8 office 128 public ToastForm(string title, string body, int duration, Image logo, byte[] sound,
7 office 129 FormAnimator.AnimationMethod animation, FormAnimator.AnimationDirection direction) : this()
2 office 130 {
15 office 131 _toastTimer.Enabled = true;
132 _toastTimer.Interval = duration;
2 office 133 labelTitle.Text = title;
134 labelBody.Text = body;
135 imageBox.Image = logo;
1 office 136  
8 office 137 _sound = sound;
138  
16 office 139 _formAnimator = new FormAnimator(this, animation, direction, 500);
2 office 140 }
141  
15 office 142 /// <summary>
143 /// Display a toast on screen.
144 /// </summary>
145 /// <param name="title">the toast title</param>
146 /// <param name="body">the toast body</param>
147 /// <param name="duration">the duration in milliseconds to display the toast on screen for</param>
148 /// <param name="logo">the toast logo</param>
149 /// <param name="sound">a sound to play when the toast is displayed</param>
8 office 150 public ToastForm(string title, string body, int duration, Image logo, byte[] sound) : this()
1 office 151 {
15 office 152 _toastTimer.Enabled = true;
153 _toastTimer.Interval = duration;
2 office 154 labelTitle.Text = title;
155 labelBody.Text = body;
156 imageBox.Image = logo;
157  
8 office 158 _sound = sound;
1 office 159 }
160  
15 office 161 /// <summary>
162 /// Display a toast on screen.
163 /// </summary>
164 /// <param name="title">the toast title</param>
165 /// <param name="body">the toast body</param>
166 /// <param name="duration">the duration in milliseconds to display the toast on screen for</param>
167 /// <param name="logo">the toast logo</param>
9 office 168 public ToastForm(string title, string body, int duration, Image logo) : this()
169 {
15 office 170 _toastTimer.Enabled = true;
171 _toastTimer.Interval = duration;
9 office 172 labelTitle.Text = title;
173 labelBody.Text = body;
174 imageBox.Image = logo;
175 }
176  
15 office 177 /// <summary>
178 /// Display a toast on screen.
179 /// </summary>
180 /// <param name="title">the toast title</param>
181 /// <param name="body">the toast body</param>
182 /// <param name="duration">the duration in milliseconds to display the toast on screen for</param>
183 /// <param name="logo">the toast logo</param>
10 office 184 public ToastForm(string title, string body, int duration, Icon logo) : this()
185 {
15 office 186 _toastTimer.Interval = duration;
10 office 187 labelTitle.Text = title;
188 labelBody.Text = body;
189 imageBox.Image = logo.ToBitmap();
190 }
191  
7 office 192 /// <summary>
11 office 193 /// Clean up any resources being used.
7 office 194 /// </summary>
195 /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
196 protected override void Dispose(bool disposing)
197 {
16 office 198 if (disposing && components != null)
199 {
200 if (_toastTimer != null)
201 {
202 _toastTimer.Dispose();
203 _toastTimer = null;
204 }
205  
206 components.Dispose();
207 }
7 office 208 base.Dispose(disposing);
209 }
210  
1 office 211 #endregion
212  
213 #region Private Delegates, Events, Enums, Properties, Indexers and Fields
214  
16 office 215 private readonly FormAnimator _formAnimator;
1 office 216  
16 office 217 private readonly byte[] _sound;
1 office 218  
16 office 219 private System.Timers.Timer _toastTimer;
1 office 220  
16 office 221 private readonly int _screenWidth;
222  
223 private readonly int _screenHeight;
224  
1 office 225 #endregion
226  
227 #region Event Handlers
228  
9 office 229 private void Notification_Load(object sender, EventArgs e)
1 office 230 {
16 office 231 Task.Factory.StartNew(() =>
232 {
233 using (var memoryStream = new MemoryStream(_sound))
9 office 234 {
16 office 235 using (var player = new SoundPlayer(memoryStream))
236 {
237 player.Play();
238 }
9 office 239 }
16 office 240 });
8 office 241  
16 office 242 try
8 office 243 {
16 office 244 lock (OpenNotificationsLock)
8 office 245 {
16 office 246 var notifications = OpenNotifications.ToArray();
8 office 247  
16 office 248 foreach (var openForm in notifications)
15 office 249 {
16 office 250 if (openForm == null)
251 {
252 continue;
253 }
7 office 254  
16 office 255 if (openForm.IsDisposed)
256 {
257 OpenNotifications.Remove(openForm);
15 office 258  
16 office 259 continue;
260 }
1 office 261  
16 office 262 if (openForm.IsHandleCreated != true)
263 {
264 continue;
265 }
4 office 266  
16 office 267 // Move each open form upwards to make room for this one
268 var handle = Handle;
269 openForm.BeginInvoke(new MethodInvoker(() =>
270 {
271 try
272 {
273 if (openForm.Handle == handle)
274 {
275 return;
276 }
1 office 277  
16 office 278 openForm.Top -= Height;
279 }
280 catch
281 {
282 Debug.WriteLine("Error while moving forms up.");
283 }
284 }));
285 }
15 office 286  
16 office 287 Invoke(new MethodInvoker(() =>
288 {
289 Location = new Point(_screenWidth - Width, _screenHeight - Height);
290 }));
291  
292 OpenNotifications.Add(this);
293  
294 // Only start the timer if it has been enabled in the constructor.
295 if (_toastTimer.Enabled)
296 {
297 _toastTimer.Start();
298 }
299 }
300 }
301 catch
15 office 302 {
16 office 303 Debug.WriteLine("Error on form load event.");
15 office 304 }
1 office 305 }
306  
307 private void Notification_FormClosed(object sender, FormClosedEventArgs e)
308 {
16 office 309 try
1 office 310 {
16 office 311 lock (OpenNotificationsLock)
7 office 312 {
16 office 313 OpenNotifications.Remove(this);
7 office 314 }
16 office 315 }
316 catch
317 {
318 Debug.WriteLine("Error in form closed event.");
319 }
320 }
15 office 321  
16 office 322 private void Notification_Shown(object sender, EventArgs e)
323 {
324 // Reverse animation direction for hiding.
325 switch (_formAnimator.Direction)
326 {
327 case FormAnimator.AnimationDirection.Up:
328 _formAnimator.Direction = FormAnimator.AnimationDirection.Down;
329 break;
330 case FormAnimator.AnimationDirection.Down:
331 _formAnimator.Direction = FormAnimator.AnimationDirection.Up;
332 break;
333 case FormAnimator.AnimationDirection.Left:
334 _formAnimator.Direction = FormAnimator.AnimationDirection.Right;
335 break;
336 case FormAnimator.AnimationDirection.Right:
337 _formAnimator.Direction = FormAnimator.AnimationDirection.Left;
338 break;
1 office 339 }
340 }
341  
15 office 342 private void ToastTimer_Elapsed(object sender, EventArgs e)
1 office 343 {
16 office 344 if (IsDisposed)
15 office 345 {
346 return;
347 }
1 office 348  
16 office 349 try
350 {
351 _toastTimer.Stop();
352 BeginInvoke(new MethodInvoker(() =>
353 {
354 lock (OpenNotificationsLock)
355 {
356 Close();
357 }
358 }));
359 }
360 catch
361 {
362 Debug.WriteLine("Error in timer elapsed event.");
363 }
1 office 364 }
365  
15 office 366 private void Toast_Click(object sender, EventArgs e)
1 office 367 {
16 office 368 try
369 {
370 lock (OpenNotificationsLock)
371 {
372 Close();
373 }
374 }
375 catch
376 {
377 Debug.WriteLine("Error in form click event.");
378 }
1 office 379 }
380  
381 #endregion
382 }
383 }