Toasts – Diff between revs 12 and 15
?pathlinks?
Rev 12 | Rev 15 | |||
---|---|---|---|---|
Line 1... | Line 1... | |||
1 | // =====COPYRIGHT===== |
1 | // =====COPYRIGHT===== |
|
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.Generic; |
6 | using System.Collections.Concurrent; |
|
7 | using System.Drawing; |
7 | using System.Drawing; |
|
- | 8 | using System.IO; |
||
8 | using System.IO; |
9 | using System.Linq; |
|
9 | using System.Media; |
10 | using System.Media; |
|
10 | using System.Windows.Forms; |
11 | using System.Windows.Forms; |
|
Line 11... | Line 12... | |||
11 | using Toasts.Properties; |
12 | using Toasts.Properties; |
|
12 | |
13 | |
|
13 | namespace Toasts |
14 | namespace Toasts |
|
14 | { |
15 | { |
|
15 | public partial class ToastForm : Form |
16 | public partial class ToastForm : Form |
|
Line 16... | Line 17... | |||
16 | { |
17 | { |
|
17 | #region Static Fields and Constants |
- | ||
18 | |
- | ||
19 | private static readonly List<ToastForm> OpenNotifications = new List<ToastForm>(); |
- | ||
20 | |
- | ||
21 | #endregion |
- | ||
22 | |
- | ||
23 | #region Public Methods |
- | ||
24 | |
- | ||
25 | /// <summary> |
- | ||
26 | /// Displays the form |
- | ||
27 | /// </summary> |
- | ||
28 | /// <remarks> |
- | ||
29 | /// Required to allow the form to determine the current foreground window before being displayed |
- | ||
30 | /// </remarks> |
- | ||
31 | public new void Show() |
- | ||
32 | { |
- | ||
33 | // Determine the current foreground window so it can be reactivated each time this form tries to get the focus |
- | ||
34 | _currentForegroundWindow = NativeMethods.GetForegroundWindow(); |
- | ||
Line 35... | Line 18... | |||
35 | |
18 | #region Static Fields and Constants |
|
Line 36... | Line 19... | |||
36 | base.Show(); |
19 | |
|
Line 62... | Line 45... | |||
62 | #region Constructors, Destructors and Finalizers |
45 | #region Constructors, Destructors and Finalizers |
|
Line 63... | Line 46... | |||
63 | |
46 | |
|
64 | private ToastForm() |
47 | private ToastForm() |
|
65 | { |
48 | { |
|
- | 49 | InitializeComponent(); |
||
- | 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; |
||
66 | InitializeComponent(); |
60 | _toastTimer.Enabled = false; |
|
Line 67... | Line 61... | |||
67 | } |
61 | } |
|
- | 62 | |
||
68 | |
63 | /// <summary> |
|
69 | /// <summary> |
64 | /// Display a toast with a title, body and a logo indefinitely on screen. |
|
70 | /// </summary> |
65 | /// </summary> |
|
71 | /// <param name="title"></param> |
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> |
||
72 | /// <param name="body"></param> |
83 | /// Display a toast on screen. |
|
73 | /// <param name="duration"></param> |
84 | /// </summary> |
|
- | 85 | /// <param name="title">the toast title</param> |
||
74 | /// <param name="image"></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> |
||
75 | /// <param name="animation"></param> |
91 | /// <param name="animation">the form animation type <see cref="FormAnimator"/></param> |
|
76 | /// <param name="direction"></param> |
92 | /// <param name="direction">the form animation direction <see cref="FormAnimator"/></param> |
|
77 | public ToastForm(string title, string body, int duration, Image logo, Image background, byte[] sound, |
93 | public ToastForm(string title, string body, int duration, Image logo, Image background, byte[] sound, |
|
- | 94 | FormAnimator.AnimationMethod animation, FormAnimator.AnimationDirection direction) : this() |
||
78 | FormAnimator.AnimationMethod animation, FormAnimator.AnimationDirection direction) : this() |
95 | { |
|
79 | { |
96 | _toastTimer.Enabled = true; |
|
80 | lifeTimer.Interval = duration; |
97 | _toastTimer.Interval = duration; |
|
81 | labelTitle.Text = title; |
98 | labelTitle.Text = title; |
|
82 | labelBody.Text = body; |
99 | labelBody.Text = body; |
|
Line 88... | Line 105... | |||
88 | _animator = new FormAnimator(this, animation, direction, 500); |
105 | _animator = new FormAnimator(this, animation, direction, 500); |
|
Line 89... | Line 106... | |||
89 | |
106 | |
|
90 | Region = Region.FromHrgn(NativeMethods.CreateRoundRectRgn(0, 0, Width - 5, Height - 5, 20, 20)); |
107 | Region = Region.FromHrgn(NativeMethods.CreateRoundRectRgn(0, 0, Width - 5, Height - 5, 20, 20)); |
|
Line -... | Line 108... | |||
- | 108 | } |
||
- | 109 | |
||
- | 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> |
||
91 | } |
118 | /// <param name="animation">the form animation type <see cref="FormAnimator"/></param> |
|
92 | |
119 | /// <param name="direction">the form animation direction <see cref="FormAnimator"/></param> |
|
93 | public ToastForm(string title, string body, int duration, Image logo, byte[] sound, |
120 | public ToastForm(string title, string body, int duration, Image logo, byte[] sound, |
|
- | 121 | FormAnimator.AnimationMethod animation, FormAnimator.AnimationDirection direction) : this() |
||
94 | FormAnimator.AnimationMethod animation, FormAnimator.AnimationDirection direction) : this() |
122 | { |
|
95 | { |
123 | _toastTimer.Enabled = true; |
|
96 | lifeTimer.Interval = duration; |
124 | _toastTimer.Interval = duration; |
|
97 | labelTitle.Text = title; |
125 | labelTitle.Text = title; |
|
Line 98... | Line 126... | |||
98 | labelBody.Text = body; |
126 | labelBody.Text = body; |
|
Line 103... | Line 131... | |||
103 | _animator = new FormAnimator(this, animation, direction, 500); |
131 | _animator = new FormAnimator(this, animation, direction, 500); |
|
Line 104... | Line 132... | |||
104 | |
132 | |
|
105 | Region = Region.FromHrgn(NativeMethods.CreateRoundRectRgn(0, 0, Width - 5, Height - 5, 20, 20)); |
133 | Region = Region.FromHrgn(NativeMethods.CreateRoundRectRgn(0, 0, Width - 5, Height - 5, 20, 20)); |
|
Line -... | Line 134... | |||
- | 134 | } |
||
- | 135 | |
||
- | 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> |
||
106 | } |
142 | /// <param name="logo">the toast logo</param> |
|
107 | |
143 | /// <param name="sound">a sound to play when the toast is displayed</param> |
|
- | 144 | public ToastForm(string title, string body, int duration, Image logo, byte[] sound) : this() |
||
108 | public ToastForm(string title, string body, int duration, Image logo, byte[] sound) : this() |
145 | { |
|
109 | { |
146 | _toastTimer.Enabled = true; |
|
110 | lifeTimer.Interval = duration; |
147 | _toastTimer.Interval = duration; |
|
111 | labelTitle.Text = title; |
148 | labelTitle.Text = title; |
|
Line 112... | Line 149... | |||
112 | labelBody.Text = body; |
149 | labelBody.Text = body; |
|
Line 118... | Line 155... | |||
118 | 500); |
155 | 500); |
|
Line 119... | Line 156... | |||
119 | |
156 | |
|
120 | Region = Region.FromHrgn(NativeMethods.CreateRoundRectRgn(0, 0, Width - 5, Height - 5, 20, 20)); |
157 | Region = Region.FromHrgn(NativeMethods.CreateRoundRectRgn(0, 0, Width - 5, Height - 5, 20, 20)); |
|
Line -... | Line 158... | |||
- | 158 | } |
||
- | 159 | |
||
- | 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> |
||
121 | } |
165 | /// <param name="duration">the duration in milliseconds to display the toast on screen for</param> |
|
122 | |
166 | /// <param name="logo">the toast logo</param> |
|
- | 167 | public ToastForm(string title, string body, int duration, Image logo) : this() |
||
123 | public ToastForm(string title, string body, int duration, Image logo) : this() |
168 | { |
|
124 | { |
169 | _toastTimer.Enabled = true; |
|
125 | lifeTimer.Interval = duration; |
170 | _toastTimer.Interval = duration; |
|
126 | labelTitle.Text = title; |
171 | labelTitle.Text = title; |
|
Line 127... | Line 172... | |||
127 | labelBody.Text = body; |
172 | labelBody.Text = body; |
|
128 | imageBox.Image = logo; |
173 | imageBox.Image = logo; |
|
Line 129... | Line 174... | |||
129 | |
174 | |
|
130 | _animator = new FormAnimator(this, FormAnimator.AnimationMethod.Slide, FormAnimator.AnimationDirection.Up, |
175 | _animator = new FormAnimator(this, FormAnimator.AnimationMethod.Slide, FormAnimator.AnimationDirection.Up, |
|
Line -... | Line 176... | |||
- | 176 | 500); |
||
- | 177 | |
||
- | 178 | Region = Region.FromHrgn(NativeMethods.CreateRoundRectRgn(0, 0, Width - 5, Height - 5, 20, 20)); |
||
- | 179 | } |
||
- | 180 | |
||
- | 181 | /// <summary> |
||
- | 182 | /// Display a toast on screen. |
||
131 | 500); |
183 | /// </summary> |
|
132 | |
184 | /// <param name="title">the toast title</param> |
|
133 | Region = Region.FromHrgn(NativeMethods.CreateRoundRectRgn(0, 0, Width - 5, Height - 5, 20, 20)); |
185 | /// <param name="body">the toast body</param> |
|
134 | } |
186 | /// <param name="duration">the duration in milliseconds to display the toast on screen for</param> |
|
135 | |
187 | /// <param name="logo">the toast logo</param> |
|
136 | public ToastForm(string title, string body, int duration, Icon logo) : this() |
188 | public ToastForm(string title, string body, int duration, Icon logo) : this() |
|
Line 137... | Line 189... | |||
137 | { |
189 | { |
|
Line 160... | Line 212... | |||
160 | |
212 | |
|
Line 161... | Line 213... | |||
161 | #region Private Delegates, Events, Enums, Properties, Indexers and Fields |
213 | #region Private Delegates, Events, Enums, Properties, Indexers and Fields |
|
Line 162... | Line -... | |||
162 | |
- | ||
163 | private readonly FormAnimator _animator; |
- | ||
164 | |
- | ||
165 | private bool _allowFocus; |
- | ||
166 | |
214 | |
|
Line -... | Line 215... | |||
- | 215 | private readonly FormAnimator _animator; |
||
- | 216 | |
||
167 | private IntPtr _currentForegroundWindow; |
217 | private byte[] _sound; |
|
Line 168... | Line 218... | |||
168 | |
218 | |
|
Line 169... | Line 219... | |||
169 | private byte[] _sound; |
219 | private readonly System.Timers.Timer _toastTimer; |
|
Line 191... | Line 241... | |||
191 | { |
241 | { |
|
192 | player.Play(); |
242 | player.Play(); |
|
193 | } |
243 | } |
|
194 | } |
244 | } |
|
Line 195... | Line -... | |||
195 | |
- | ||
196 | // Display the form just above the system tray. |
- | ||
197 | Location = new Point(Screen.PrimaryScreen.WorkingArea.Width - Width, |
- | ||
198 | Screen.PrimaryScreen.WorkingArea.Height - Height); |
- | ||
199 | |
245 | |
|
200 | // Move each open form upwards to make room for this one |
246 | // Move each open form upwards to make room for this one |
|
201 | foreach (var openForm in OpenNotifications) |
247 | foreach (var openForm in OpenNotifications.Values) |
|
202 | { |
248 | { |
|
203 | if (openForm.InvokeRequired) |
249 | if (openForm.InvokeRequired) |
|
- | 250 | { |
||
- | 251 | void Move() |
||
204 | { |
252 | { |
|
- | 253 | openForm.Top -= Height; |
||
- | 254 | } |
||
205 | Action action = delegate { openForm.Top -= Height; }; |
255 | |
|
Line 206... | Line 256... | |||
206 | openForm.Invoke(action); |
256 | openForm.Invoke((Action)Move); |
|
207 | |
257 | |
|
Line 208... | Line 258... | |||
208 | continue; |
258 | continue; |
|
209 | } |
259 | } |
|
Line 210... | Line 260... | |||
210 | |
260 | |
|
- | 261 | openForm.Top -= Height; |
||
211 | openForm.Top -= Height; |
262 | } |
|
212 | } |
- | ||
Line 213... | Line 263... | |||
213 | |
263 | |
|
214 | OpenNotifications.Add(this); |
264 | // Display the form just above the system tray. |
|
215 | lifeTimer.Start(); |
265 | Location = new Point(Screen.PrimaryScreen.WorkingArea.Width - Width, |
|
216 | } |
266 | Screen.PrimaryScreen.WorkingArea.Height - Height); |
|
217 | |
267 | |
|
218 | private void Notification_Activated(object sender, EventArgs e) |
268 | OpenNotifications.TryAdd(Handle, this); |
|
- | 269 | |
||
219 | { |
270 | // Only start the timer if it has been enabled in the constructor. |
|
Line 220... | Line 271... | |||
220 | // Prevent the form taking focus when it is initially shown |
271 | if (_toastTimer.Enabled) |
|
221 | if (!_allowFocus) |
272 | { |
|
222 | // Activate the window that previously had focus |
- | ||
223 | NativeMethods.SetForegroundWindow(_currentForegroundWindow); |
- | ||
224 | } |
- | ||
225 | |
273 | _toastTimer.Start(); |
|
226 | private void Notification_Shown(object sender, EventArgs e) |
274 | } |
|
227 | { |
275 | } |
|
228 | // Once the animation has completed the form can receive focus |
276 | |
|
Line 229... | Line 277... | |||
229 | _allowFocus = true; |
277 | private void Notification_Shown(object sender, EventArgs e) |
|
230 | |
278 | { |
|
231 | // Close the form by sliding down. |
279 | // Close the form by sliding down. |
|
232 | _animator.Duration = 0; |
280 | _animator.Duration = 0; |
|
233 | _animator.Direction = FormAnimator.AnimationDirection.Down; |
281 | _animator.Direction = FormAnimator.AnimationDirection.Down; |
|
234 | } |
282 | } |
|
235 | |
- | ||
236 | private void Notification_FormClosed(object sender, FormClosedEventArgs e) |
283 | |
|
Line 237... | Line 284... | |||
237 | { |
284 | private void Notification_FormClosed(object sender, FormClosedEventArgs e) |
|
238 | // Move down any open forms above this one |
285 | { |
|
- | 286 | // Move down any open forms above this one |
||
- | 287 | foreach (var openForm in OpenNotifications.Values) |
||
239 | foreach (var openForm in OpenNotifications) |
288 | { |
|
- | 289 | if (openForm.Handle == Handle) |
||
- | 290 | continue; |
||
240 | { |
291 | |
|
- | 292 | if (openForm.InvokeRequired) |
||
- | 293 | { |
||
241 | if (openForm == this) |
294 | void Move() |
|
- | 295 | { |
||
- | 296 | openForm.Top += Height; |
||
242 | // Remaining forms are below this one |
297 | } |
|
Line 243... | Line 298... | |||
243 | break; |
298 | |
|
244 | |
299 | openForm.Invoke((Action)Move); |
|
Line 245... | Line 300... | |||
245 | if (openForm.InvokeRequired) |
300 | |
|
246 | { |
301 | continue; |
|
247 | Action action = delegate { openForm.Top += Height; }; |
302 | } |
|
248 | openForm.Invoke(action); |
303 | |
|
- | 304 | openForm.Top += Height; |
||
Line 249... | Line -... | |||
249 | } |
- | ||
250 | } |
- | ||
251 | |
305 | } |
|
252 | OpenNotifications.Remove(this); |
306 | |
|
Line 253... | Line -... | |||
253 | } |
- | ||
254 | |
- | ||
255 | private void LifeTimer_Tick(object sender, EventArgs e) |
307 | OpenNotifications.TryRemove(Handle, out _); |
|
256 | { |
308 | } |
|
Line 257... | Line 309... | |||
257 | Close(); |
309 | |
|
258 | } |
310 | private void ToastTimer_Elapsed(object sender, EventArgs e) |
|
259 | |
311 | { |
|
260 | private void Notification_Click(object sender, EventArgs e) |
312 | if (InvokeRequired) |
|
Line 261... | Line 313... | |||
261 | { |
313 | { |