Toasts – Diff between revs 15 and 16
?pathlinks?
Rev 15 | Rev 16 | |||
---|---|---|---|---|
Line 2... | Line 2... | |||
2 | // Code originally retrieved from http://www.vbforums.com/showthread.php?t=547778 - no license information supplied |
2 | // Code originally retrieved from http://www.vbforums.com/showthread.php?t=547778 - no license information supplied |
|
3 | // =====COPYRIGHT===== |
3 | // =====COPYRIGHT===== |
|
Line 4... | Line 4... | |||
4 | |
4 | |
|
5 | using System; |
5 | using System; |
|
- | 6 | using System.Collections.Concurrent; |
||
- | 7 | using System.Collections.Generic; |
||
6 | using System.Collections.Concurrent; |
8 | using System.Diagnostics; |
|
7 | using System.Drawing; |
9 | using System.Drawing; |
|
8 | using System.IO; |
10 | using System.IO; |
|
9 | using System.Linq; |
11 | using System.Linq; |
|
- | 12 | using System.Media; |
||
- | 13 | using System.Threading; |
||
10 | using System.Media; |
14 | using System.Threading.Tasks; |
|
11 | using System.Windows.Forms; |
15 | using System.Windows.Forms; |
|
Line 12... | Line 16... | |||
12 | using Toasts.Properties; |
16 | using Toasts.Properties; |
|
13 | |
17 | |
|
14 | namespace Toasts |
18 | namespace Toasts |
|
15 | { |
19 | { |
|
16 | public partial class ToastForm : Form |
20 | public partial class ToastForm : Form |
|
Line -... | Line 21... | |||
- | 21 | { |
||
- | 22 | #region Static Fields and Constants |
||
17 | { |
23 | |
|
Line 18... | Line 24... | |||
18 | #region Static Fields and Constants |
24 | private static readonly object OpenNotificationsLock = new object(); |
|
Line 19... | Line 25... | |||
19 | |
25 | |
|
Line 45... | Line 51... | |||
45 | #region Constructors, Destructors and Finalizers |
51 | #region Constructors, Destructors and Finalizers |
|
Line 46... | Line 52... | |||
46 | |
52 | |
|
47 | private ToastForm() |
53 | private ToastForm() |
|
48 | { |
54 | { |
|
- | 55 | InitializeComponent(); |
||
- | 56 | Region = Region.FromHrgn(NativeMethods.CreateRoundRectRgn(0, 0, Width - 5, Height - 5, 20, 20)); |
||
- | 57 | |
||
- | 58 | _screenWidth = Screen.PrimaryScreen.WorkingArea.Width; |
||
Line -... | Line 59... | |||
- | 59 | _screenHeight = Screen.PrimaryScreen.WorkingArea.Height; |
||
- | 60 | |
||
- | 61 | _formAnimator = new FormAnimator(this, FormAnimator.AnimationMethod.Slide, FormAnimator.AnimationDirection.Up, |
||
49 | InitializeComponent(); |
62 | 500); |
|
50 | |
63 | |
|
51 | foreach (var control in Controls.Cast<Control>()) |
64 | using (var memoryStream = new MemoryStream()) |
|
- | 65 | { |
||
52 | { |
66 | Resources.normal.CopyTo(memoryStream); |
|
Line 53... | Line 67... | |||
53 | control.Click += Toast_Click; |
67 | |
|
- | 68 | memoryStream.Position = 0L; |
||
Line 54... | Line 69... | |||
54 | } |
69 | |
|
55 | |
70 | _sound = memoryStream.ToArray(); |
|
56 | Click += Toast_Click; |
71 | } |
|
57 | |
72 | |
|
Line 70... | Line 85... | |||
70 | { |
85 | { |
|
71 | _toastTimer.Enabled = false; |
86 | _toastTimer.Enabled = false; |
|
72 | labelTitle.Text = title; |
87 | labelTitle.Text = title; |
|
73 | labelBody.Text = body; |
88 | labelBody.Text = body; |
|
74 | imageBox.Image = logo; |
89 | 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 | } |
90 | } |
|
Line 81... | Line 91... | |||
81 | |
91 | |
|
82 | /// <summary> |
92 | /// <summary> |
|
83 | /// Display a toast on screen. |
93 | /// Display a toast on screen. |
|
Line 100... | Line 110... | |||
100 | imageBox.Image = logo; |
110 | imageBox.Image = logo; |
|
101 | BackgroundImage = background; |
111 | BackgroundImage = background; |
|
Line 102... | Line 112... | |||
102 | |
112 | |
|
Line 103... | Line 113... | |||
103 | _sound = sound; |
113 | _sound = sound; |
|
104 | |
- | ||
105 | _animator = new FormAnimator(this, animation, direction, 500); |
- | ||
106 | |
114 | |
|
Line 107... | Line 115... | |||
107 | Region = Region.FromHrgn(NativeMethods.CreateRoundRectRgn(0, 0, Width - 5, Height - 5, 20, 20)); |
115 | _formAnimator = new FormAnimator(this, animation, direction, 500); |
|
108 | } |
116 | } |
|
109 | |
117 | |
|
Line 126... | Line 134... | |||
126 | labelBody.Text = body; |
134 | labelBody.Text = body; |
|
127 | imageBox.Image = logo; |
135 | imageBox.Image = logo; |
|
Line 128... | Line 136... | |||
128 | |
136 | |
|
Line 129... | Line 137... | |||
129 | _sound = sound; |
137 | _sound = sound; |
|
130 | |
- | ||
131 | _animator = new FormAnimator(this, animation, direction, 500); |
- | ||
132 | |
138 | |
|
Line 133... | Line 139... | |||
133 | Region = Region.FromHrgn(NativeMethods.CreateRoundRectRgn(0, 0, Width - 5, Height - 5, 20, 20)); |
139 | _formAnimator = new FormAnimator(this, animation, direction, 500); |
|
134 | } |
140 | } |
|
135 | |
141 | |
|
Line 148... | Line 154... | |||
148 | labelTitle.Text = title; |
154 | labelTitle.Text = title; |
|
149 | labelBody.Text = body; |
155 | labelBody.Text = body; |
|
150 | imageBox.Image = logo; |
156 | imageBox.Image = logo; |
|
Line 151... | Line 157... | |||
151 | |
157 | |
|
152 | _sound = sound; |
- | ||
153 | |
- | ||
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)); |
158 | _sound = sound; |
|
Line 158... | Line 159... | |||
158 | } |
159 | } |
|
159 | |
160 | |
|
160 | /// <summary> |
161 | /// <summary> |
|
Line 169... | Line 170... | |||
169 | _toastTimer.Enabled = true; |
170 | _toastTimer.Enabled = true; |
|
170 | _toastTimer.Interval = duration; |
171 | _toastTimer.Interval = duration; |
|
171 | labelTitle.Text = title; |
172 | labelTitle.Text = title; |
|
172 | labelBody.Text = body; |
173 | labelBody.Text = body; |
|
173 | imageBox.Image = logo; |
174 | 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 | } |
175 | } |
|
Line 180... | Line 176... | |||
180 | |
176 | |
|
181 | /// <summary> |
177 | /// <summary> |
|
182 | /// Display a toast on screen. |
178 | /// Display a toast on screen. |
|
Line 189... | Line 185... | |||
189 | { |
185 | { |
|
190 | _toastTimer.Interval = duration; |
186 | _toastTimer.Interval = duration; |
|
191 | labelTitle.Text = title; |
187 | labelTitle.Text = title; |
|
192 | labelBody.Text = body; |
188 | labelBody.Text = body; |
|
193 | imageBox.Image = logo.ToBitmap(); |
189 | 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 | } |
190 | } |
|
Line 200... | Line 191... | |||
200 | |
191 | |
|
201 | /// <summary> |
192 | /// <summary> |
|
202 | /// Clean up any resources being used. |
193 | /// Clean up any resources being used. |
|
203 | /// </summary> |
194 | /// </summary> |
|
204 | /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param> |
195 | /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param> |
|
205 | protected override void Dispose(bool disposing) |
196 | protected override void Dispose(bool disposing) |
|
206 | { |
197 | { |
|
- | 198 | if (disposing && components != null) |
||
- | 199 | { |
||
- | 200 | if (_toastTimer != null) |
||
- | 201 | { |
||
- | 202 | _toastTimer.Dispose(); |
||
- | 203 | _toastTimer = null; |
||
- | 204 | } |
||
- | 205 | |
||
- | 206 | components.Dispose(); |
||
207 | if (disposing && components != null) components.Dispose(); |
207 | } |
|
208 | base.Dispose(disposing); |
208 | base.Dispose(disposing); |
|
Line 209... | Line 209... | |||
209 | } |
209 | } |
|
Line 210... | Line 210... | |||
210 | |
210 | |
|
Line 211... | Line 211... | |||
211 | #endregion |
211 | #endregion |
|
Line 212... | Line 212... | |||
212 | |
212 | |
|
Line 213... | Line 213... | |||
213 | #region Private Delegates, Events, Enums, Properties, Indexers and Fields |
213 | #region Private Delegates, Events, Enums, Properties, Indexers and Fields |
|
- | 214 | |
||
- | 215 | private readonly FormAnimator _formAnimator; |
||
- | 216 | |
||
- | 217 | private readonly byte[] _sound; |
||
Line 214... | Line 218... | |||
214 | |
218 | |
|
Line 215... | Line 219... | |||
215 | private readonly FormAnimator _animator; |
219 | private System.Timers.Timer _toastTimer; |
|
Line 216... | Line 220... | |||
216 | |
220 | |
|
217 | private byte[] _sound; |
221 | private readonly int _screenWidth; |
|
218 | |
- | ||
219 | private readonly System.Timers.Timer _toastTimer; |
- | ||
220 | |
- | ||
221 | #endregion |
- | ||
222 | |
- | ||
223 | #region Event Handlers |
- | ||
224 | |
222 | |
|
225 | private void Notification_Load(object sender, EventArgs e) |
- | ||
226 | { |
- | ||
227 | // Play the sound. |
- | ||
228 | if (_sound == null) |
- | ||
229 | using (var memoryStream = new MemoryStream()) |
- | ||
230 | { |
223 | private readonly int _screenHeight; |
|
231 | Resources.normal.CopyTo(memoryStream); |
224 | |
|
232 | |
225 | #endregion |
|
- | 226 | |
||
- | 227 | #region Event Handlers |
||
233 | memoryStream.Position = 0L; |
228 | |
|
- | 229 | private void Notification_Load(object sender, EventArgs e) |
||
234 | |
230 | { |
|
235 | _sound = memoryStream.ToArray(); |
231 | Task.Factory.StartNew(() => |
|
Line 236... | Line -... | |||
236 | } |
- | ||
237 | |
232 | { |
|
238 | using (var memoryStream = new MemoryStream(_sound)) |
233 | using (var memoryStream = new MemoryStream(_sound)) |
|
239 | { |
234 | { |
|
240 | using (var player = new SoundPlayer(memoryStream)) |
235 | using (var player = new SoundPlayer(memoryStream)) |
|
- | 236 | { |
||
- | 237 | player.Play(); |
||
241 | { |
238 | } |
|
242 | player.Play(); |
239 | } |
|
- | 240 | }); |
||
- | 241 | |
||
- | 242 | try |
||
- | 243 | { |
||
- | 244 | lock (OpenNotificationsLock) |
||
- | 245 | { |
||
- | 246 | var notifications = OpenNotifications.ToArray(); |
||
- | 247 | |
||
- | 248 | foreach (var openForm in notifications) |
||
- | 249 | { |
||
- | 250 | if (openForm == null) |
||
- | 251 | { |
||
- | 252 | continue; |
||
- | 253 | } |
||
- | 254 | |
||
- | 255 | if (openForm.IsDisposed) |
||
- | 256 | { |
||
- | 257 | OpenNotifications.Remove(openForm); |
||
- | 258 | |
||
- | 259 | continue; |
||
- | 260 | } |
||
- | 261 | |
||
- | 262 | if (openForm.IsHandleCreated != true) |
||
- | 263 | { |
||
- | 264 | continue; |
||
- | 265 | } |
||
- | 266 | |
||
- | 267 | // Move each open form upwards to make room for this one |
||
243 | } |
268 | var handle = Handle; |
|
- | 269 | openForm.BeginInvoke(new MethodInvoker(() => |
||
- | 270 | { |
||
- | 271 | try |
||
- | 272 | { |
||
- | 273 | if (openForm.Handle == handle) |
||
- | 274 | { |
||
244 | } |
275 | return; |
|
Line 245... | Line 276... | |||
245 | |
276 | } |
|
- | 277 | |
||
- | 278 | openForm.Top -= Height; |
||
- | 279 | } |
||
Line 246... | Line 280... | |||
246 | // Move each open form upwards to make room for this one |
280 | catch |
|
247 | foreach (var openForm in OpenNotifications.Values) |
- | ||
Line -... | Line 281... | |||
- | 281 | { |
||
- | 282 | Debug.WriteLine("Error while moving forms up."); |
||
- | 283 | } |
||
248 | { |
284 | })); |
|
- | 285 | } |
||
- | 286 | |
||
249 | if (openForm.InvokeRequired) |
287 | Invoke(new MethodInvoker(() => |
|
250 | { |
- | ||
251 | void Move() |
- | ||
252 | { |
- | ||
253 | openForm.Top -= Height; |
- | ||
254 | } |
- | ||
255 | |
- | ||
256 | openForm.Invoke((Action)Move); |
- | ||
257 | |
- | ||
258 | continue; |
288 | { |
|
259 | } |
289 | Location = new Point(_screenWidth - Width, _screenHeight - Height); |
|
260 | |
290 | })); |
|
261 | openForm.Top -= Height; |
291 | |
|
262 | } |
292 | OpenNotifications.Add(this); |
|
Line 263... | Line -... | |||
263 | |
- | ||
264 | // Display the form just above the system tray. |
- | ||
265 | Location = new Point(Screen.PrimaryScreen.WorkingArea.Width - Width, |
- | ||
266 | Screen.PrimaryScreen.WorkingArea.Height - Height); |
- | ||
267 | |
- | ||
268 | OpenNotifications.TryAdd(Handle, this); |
- | ||
269 | |
- | ||
270 | // Only start the timer if it has been enabled in the constructor. |
293 | |
|
271 | if (_toastTimer.Enabled) |
294 | // Only start the timer if it has been enabled in the constructor. |
|
272 | { |
295 | if (_toastTimer.Enabled) |
|
273 | _toastTimer.Start(); |
- | ||
274 | } |
296 | { |
|
275 | } |
- | ||
276 | |
- | ||
277 | private void Notification_Shown(object sender, EventArgs e) |
- | ||
278 | { |
297 | _toastTimer.Start(); |
|
279 | // Close the form by sliding down. |
298 | } |
|
280 | _animator.Duration = 0; |
- | ||
281 | _animator.Direction = FormAnimator.AnimationDirection.Down; |
- | ||
282 | } |
- | ||
283 | |
- | ||
284 | private void Notification_FormClosed(object sender, FormClosedEventArgs e) |
- | ||
285 | { |
299 | } |
|
286 | // Move down any open forms above this one |
- | ||
287 | foreach (var openForm in OpenNotifications.Values) |
- | ||
288 | { |
300 | } |
|
289 | if (openForm.Handle == Handle) |
- | ||
290 | continue; |
- | ||
291 | |
301 | catch |
|
- | 302 | { |
||
- | 303 | Debug.WriteLine("Error on form load event."); |
||
- | 304 | } |
||
- | 305 | } |
||
- | 306 | |
||
Line 292... | Line 307... | |||
292 | if (openForm.InvokeRequired) |
307 | private void Notification_FormClosed(object sender, FormClosedEventArgs e) |
|
- | 308 | { |
||
- | 309 | try |
||
- | 310 | { |
||
- | 311 | lock (OpenNotificationsLock) |
||
- | 312 | { |
||
- | 313 | OpenNotifications.Remove(this); |
||
- | 314 | } |
||
- | 315 | } |
||
- | 316 | catch |
||
- | 317 | { |
||
- | 318 | Debug.WriteLine("Error in form closed event."); |
||
- | 319 | } |
||
- | 320 | } |
||
- | 321 | |
||
- | 322 | private void Notification_Shown(object sender, EventArgs e) |
||
- | 323 | { |
||
- | 324 | // Reverse animation direction for hiding. |
||
293 | { |
325 | switch (_formAnimator.Direction) |
|
Line 294... | Line 326... | |||
294 | void Move() |
326 | { |
|
295 | { |
327 | case FormAnimator.AnimationDirection.Up: |
|
296 | openForm.Top += Height; |
328 | _formAnimator.Direction = FormAnimator.AnimationDirection.Down; |
|
297 | } |
329 | break; |
|
298 | |
- | ||
299 | openForm.Invoke((Action)Move); |
- | ||
300 | |
330 | case FormAnimator.AnimationDirection.Down: |
|
301 | continue; |
331 | _formAnimator.Direction = FormAnimator.AnimationDirection.Up; |
|
Line -... | Line 332... | |||
- | 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; |
||
- | 339 | } |
||
- | 340 | } |
||
302 | } |
341 | |
|
- | 342 | private void ToastTimer_Elapsed(object sender, EventArgs e) |
||
- | 343 | { |
||
- | 344 | if (IsDisposed) |
||
- | 345 | { |
||
- | 346 | return; |
||
303 | |
347 | } |
|
Line 304... | Line 348... | |||
304 | openForm.Top += Height; |
348 | |
|
305 | } |
349 | try |
|
- | 350 | { |
||
- | 351 | _toastTimer.Stop(); |
||
- | 352 | BeginInvoke(new MethodInvoker(() => |
||
- | 353 | { |
||
306 | |
354 | lock (OpenNotificationsLock) |
|
- | 355 | { |
||
- | 356 | Close(); |
||
- | 357 | } |
||
- | 358 | })); |
||
- | 359 | } |
||
- | 360 | catch |
||
307 | OpenNotifications.TryRemove(Handle, out _); |
361 | { |
|
Line 308... | Line 362... | |||
308 | } |
362 | Debug.WriteLine("Error in timer elapsed event."); |
|
309 | |
363 | } |
|
310 | private void ToastTimer_Elapsed(object sender, EventArgs e) |
364 | } |
|
311 | { |
365 | |