Toasts – Blame information for rev 8
?pathlinks?
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; |
||
6 | using System.Collections.Generic; |
||
7 | using System.Drawing; |
||
8 | office | 8 | using System.IO; |
9 | using System.Media; |
||
10 | using System.Reflection; |
||
11 | using System.Threading.Tasks; |
||
1 | office | 12 | using System.Windows.Forms; |
13 | |||
14 | namespace Toasts |
||
15 | { |
||
2 | office | 16 | public partial class ToastForm : Form |
1 | office | 17 | { |
18 | #region Static Fields and Constants |
||
19 | |||
2 | office | 20 | private static readonly List<ToastForm> OpenNotifications = new List<ToastForm>(); |
1 | office | 21 | |
22 | #endregion |
||
23 | |||
2 | office | 24 | #region Public Methods |
25 | |||
26 | /// <summary> |
||
27 | /// Displays the form |
||
28 | /// </summary> |
||
29 | /// <remarks> |
||
30 | /// Required to allow the form to determine the current foreground window before being displayed |
||
31 | /// </remarks> |
||
32 | public new void Show() |
||
33 | { |
||
34 | // Determine the current foreground window so it can be reactivated each time this form tries to get the focus |
||
35 | _currentForegroundWindow = NativeMethods.GetForegroundWindow(); |
||
36 | |||
37 | base.Show(); |
||
38 | } |
||
39 | |||
40 | #endregion |
||
41 | |||
8 | office | 42 | #region Private Methods |
43 | |||
44 | private static async Task<byte[]> LoadResource(string resource) |
||
45 | { |
||
46 | var assembly = Assembly.GetExecutingAssembly(); |
||
47 | |||
48 | using (var manifestResourceStream = assembly.GetManifestResourceStream(resource)) |
||
49 | { |
||
50 | if (manifestResourceStream == null) |
||
51 | { |
||
52 | return null; |
||
53 | } |
||
54 | |||
55 | var memoryStream = new MemoryStream(); |
||
56 | |||
57 | await manifestResourceStream.CopyToAsync(memoryStream); |
||
58 | |||
59 | memoryStream.Position = 0L; |
||
60 | |||
61 | return memoryStream.ToArray(); |
||
62 | } |
||
63 | } |
||
64 | |||
65 | #endregion |
||
66 | |||
1 | office | 67 | #region Constructors, Destructors and Finalizers |
68 | |||
8 | office | 69 | private ToastForm() |
7 | office | 70 | { |
71 | InitializeComponent(); |
||
72 | } |
||
8 | office | 73 | |
1 | office | 74 | /// <summary> |
75 | /// </summary> |
||
76 | /// <param name="title"></param> |
||
77 | /// <param name="body"></param> |
||
78 | /// <param name="duration"></param> |
||
79 | /// <param name="image"></param> |
||
80 | /// <param name="animation"></param> |
||
81 | /// <param name="direction"></param> |
||
8 | office | 82 | public ToastForm(string title, string body, int duration, Image logo, Image background, byte[] sound, |
7 | office | 83 | FormAnimator.AnimationMethod animation, FormAnimator.AnimationDirection direction) : this() |
1 | office | 84 | { |
85 | lifeTimer.Interval = duration; |
||
86 | labelTitle.Text = title; |
||
87 | labelBody.Text = body; |
||
88 | imageBox.Image = logo; |
||
89 | BackgroundImage = background; |
||
90 | |||
8 | office | 91 | _sound = sound; |
92 | |||
1 | office | 93 | _animator = new FormAnimator(this, animation, direction, 500); |
94 | |||
95 | Region = Region.FromHrgn(NativeMethods.CreateRoundRectRgn(0, 0, Width - 5, Height - 5, 20, 20)); |
||
96 | } |
||
97 | |||
8 | office | 98 | public ToastForm(string title, string body, int duration, Image logo, byte[] sound, |
7 | office | 99 | FormAnimator.AnimationMethod animation, FormAnimator.AnimationDirection direction) : this() |
2 | office | 100 | { |
101 | lifeTimer.Interval = duration; |
||
102 | labelTitle.Text = title; |
||
103 | labelBody.Text = body; |
||
104 | imageBox.Image = logo; |
||
1 | office | 105 | |
8 | office | 106 | _sound = sound; |
107 | |||
2 | office | 108 | _animator = new FormAnimator(this, animation, direction, 500); |
109 | |||
110 | Region = Region.FromHrgn(NativeMethods.CreateRoundRectRgn(0, 0, Width - 5, Height - 5, 20, 20)); |
||
111 | } |
||
112 | |||
8 | office | 113 | public ToastForm(string title, string body, int duration, Image logo, byte[] sound) : this() |
1 | office | 114 | { |
2 | office | 115 | lifeTimer.Interval = duration; |
116 | labelTitle.Text = title; |
||
117 | labelBody.Text = body; |
||
118 | imageBox.Image = logo; |
||
119 | |||
8 | office | 120 | _sound = sound; |
121 | |||
2 | office | 122 | _animator = new FormAnimator(this, FormAnimator.AnimationMethod.Slide, FormAnimator.AnimationDirection.Up, |
123 | 500); |
||
124 | |||
125 | Region = Region.FromHrgn(NativeMethods.CreateRoundRectRgn(0, 0, Width - 5, Height - 5, 20, 20)); |
||
1 | office | 126 | } |
127 | |||
7 | office | 128 | /// <summary> |
129 | /// Clean up any resources being used. |
||
130 | /// </summary> |
||
131 | /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param> |
||
132 | protected override void Dispose(bool disposing) |
||
133 | { |
||
134 | if (disposing && (components != null)) |
||
135 | { |
||
136 | components.Dispose(); |
||
137 | } |
||
138 | base.Dispose(disposing); |
||
139 | } |
||
140 | |||
1 | office | 141 | #endregion |
142 | |||
143 | #region Private Delegates, Events, Enums, Properties, Indexers and Fields |
||
144 | |||
145 | private readonly FormAnimator _animator; |
||
146 | |||
147 | private bool _allowFocus; |
||
148 | |||
149 | private IntPtr _currentForegroundWindow; |
||
150 | |||
8 | office | 151 | private byte[] _sound; |
152 | |||
1 | office | 153 | #endregion |
154 | |||
155 | #region Event Handlers |
||
156 | |||
8 | office | 157 | private async void Notification_Load(object sender, EventArgs e) |
1 | office | 158 | { |
8 | office | 159 | // Play the sound. |
160 | if (_sound == null) |
||
161 | { |
||
162 | _sound = await LoadResource($"Toasts.Sounds.default.wav"); |
||
163 | } |
||
164 | |||
165 | using (var memoryStream = new MemoryStream(_sound)) |
||
166 | { |
||
167 | using (var player = new SoundPlayer(memoryStream)) |
||
168 | { |
||
169 | player.Play(); |
||
170 | } |
||
171 | } |
||
172 | |||
1 | office | 173 | // Display the form just above the system tray. |
174 | Location = new Point(Screen.PrimaryScreen.WorkingArea.Width - Width, |
||
175 | Screen.PrimaryScreen.WorkingArea.Height - Height); |
||
176 | |||
177 | // Move each open form upwards to make room for this one |
||
4 | office | 178 | foreach (var openForm in OpenNotifications) |
179 | { |
||
180 | if (openForm.InvokeRequired) |
||
181 | { |
||
182 | Action action = delegate { openForm.Top -= Height; }; |
||
183 | openForm.Invoke(action); |
||
7 | office | 184 | |
185 | continue; |
||
4 | office | 186 | } |
1 | office | 187 | |
4 | office | 188 | openForm.Top -= Height; |
189 | } |
||
190 | |||
1 | office | 191 | OpenNotifications.Add(this); |
192 | lifeTimer.Start(); |
||
193 | } |
||
194 | |||
195 | private void Notification_Activated(object sender, EventArgs e) |
||
196 | { |
||
197 | // Prevent the form taking focus when it is initially shown |
||
198 | if (!_allowFocus) |
||
7 | office | 199 | { |
1 | office | 200 | // Activate the window that previously had focus |
201 | NativeMethods.SetForegroundWindow(_currentForegroundWindow); |
||
7 | office | 202 | } |
1 | office | 203 | } |
204 | |||
205 | private void Notification_Shown(object sender, EventArgs e) |
||
206 | { |
||
207 | // Once the animation has completed the form can receive focus |
||
208 | _allowFocus = true; |
||
209 | |||
210 | // Close the form by sliding down. |
||
211 | _animator.Duration = 0; |
||
212 | _animator.Direction = FormAnimator.AnimationDirection.Down; |
||
213 | } |
||
214 | |||
215 | private void Notification_FormClosed(object sender, FormClosedEventArgs e) |
||
216 | { |
||
217 | // Move down any open forms above this one |
||
218 | foreach (var openForm in OpenNotifications) |
||
219 | { |
||
220 | if (openForm == this) |
||
221 | // Remaining forms are below this one |
||
222 | break; |
||
223 | |||
7 | office | 224 | if (openForm.InvokeRequired) |
225 | { |
||
226 | Action action = delegate { openForm.Top += Height; }; |
||
227 | openForm.Invoke(action); |
||
228 | |||
229 | continue; |
||
230 | } |
||
1 | office | 231 | } |
232 | |||
233 | OpenNotifications.Remove(this); |
||
234 | } |
||
235 | |||
236 | private void LifeTimer_Tick(object sender, EventArgs e) |
||
237 | { |
||
238 | Close(); |
||
239 | } |
||
240 | |||
241 | private void Notification_Click(object sender, EventArgs e) |
||
242 | { |
||
243 | Close(); |
||
244 | } |
||
245 | |||
246 | private void LabelTitle_Click(object sender, EventArgs e) |
||
247 | { |
||
248 | Close(); |
||
249 | } |
||
250 | |||
251 | private void LabelRO_Click(object sender, EventArgs e) |
||
252 | { |
||
253 | Close(); |
||
254 | } |
||
255 | |||
256 | #endregion |
||
257 | } |
||
258 | } |