-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathWindows7ProgressBar.cs
347 lines (301 loc) · 10.9 KB
/
Windows7ProgressBar.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
using System;
using System.ComponentModel;
using System.ComponentModel.Design;
using System.Drawing;
using System.Runtime.InteropServices;
using System.Windows.Forms;
// Windows7ProgressBar v1.0, created by Wyatt O'Day
// Visit: http://wyday.com/windows-7-progress-bar/
namespace wyDay.Controls {
/// <summary>
/// Represents the thumbnail progress bar state.
/// </summary>
public enum ThumbnailProgressState {
/// <summary>
/// No progress is displayed.
/// </summary>
NoProgress = 0,
/// <summary>
/// The progress is indeterminate (marquee).
/// </summary>
Indeterminate = 0x1,
/// <summary>
/// Normal progress is displayed.
/// </summary>
Normal = 0x2,
/// <summary>
/// An error occurred (red).
/// </summary>
Error = 0x4,
/// <summary>
/// The operation is paused (yellow).
/// </summary>
Paused = 0x8
}
/// <summary>
/// The progress bar state for Windows Vista & 7
/// </summary>
public enum ProgressBarState {
/// <summary>
/// Indicates normal progress
/// </summary>
Normal = 1,
/// <summary>
/// Indicates an error in the progress
/// </summary>
Error = 2,
/// <summary>
/// Indicates paused progress
/// </summary>
Pause = 3
}
// Based on Rob Jarett's wrappers for the desktop integration PDC demos.
[ComImport]
[Guid("ea1afb91-9e28-4b86-90e9-9e9f8a5eefaf")]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
internal interface ITaskbarList3 {
// ITaskbarList
[PreserveSig]
void HrInit();
[PreserveSig]
void AddTab(IntPtr hwnd);
[PreserveSig]
void DeleteTab(IntPtr hwnd);
[PreserveSig]
void ActivateTab(IntPtr hwnd);
[PreserveSig]
void SetActiveAlt(IntPtr hwnd);
// ITaskbarList2
[PreserveSig]
void MarkFullscreenWindow(IntPtr hwnd, [MarshalAs(UnmanagedType.Bool)] bool fFullscreen);
// ITaskbarList3
void SetProgressValue(IntPtr hwnd, ulong ullCompleted, ulong ullTotal);
void SetProgressState(IntPtr hwnd, ThumbnailProgressState tbpFlags);
// yadda, yadda - there's more to the interface, but we don't need it.
}
[Guid("56FDF344-FD6D-11d0-958A-006097C9A090")]
[ClassInterface(ClassInterfaceType.None)]
[ComImport]
internal class CTaskbarList {
}
/// <summary>
/// The primary coordinator of the Windows 7 taskbar-related activities.
/// </summary>
public sealed class Windows7Taskbar {
private Windows7Taskbar() {
}
private static ITaskbarList3 _taskbarList;
internal static ITaskbarList3 TaskbarList {
get {
if (_taskbarList is null) {
lock (typeof(Windows7Taskbar)) {
if (_taskbarList is null) {
_taskbarList = (ITaskbarList3)new CTaskbarList();
_taskbarList.HrInit();
}
}
}
return _taskbarList;
}
}
private static readonly OperatingSystem osInfo = Environment.OSVersion;
internal static bool Windows7OrGreater {
get {
return osInfo.Version.Major == 6 && osInfo.Version.Minor >= 1 || osInfo.Version.Major > 6;
}
}
/// <summary>
/// Sets the progress state of the specified window's
/// taskbar button.
/// </summary>
/// <param name="hwnd">The window handle.</param>
/// <param name="state">The progress state.</param>
public static void SetProgressState(IntPtr hwnd, ThumbnailProgressState state) {
if (Windows7OrGreater) {
TaskbarList.SetProgressState(hwnd, state);
}
}
/// <summary>
/// Sets the progress value of the specified window's
/// taskbar button.
/// </summary>
/// <param name="hwnd">The window handle.</param>
/// <param name="current">The current value.</param>
/// <param name="maximum">The maximum value.</param>
public static void SetProgressValue(IntPtr hwnd, ulong current, ulong maximum) {
if (Windows7OrGreater) {
TaskbarList.SetProgressValue(hwnd, current, maximum);
}
}
[DllImport("user32.dll", CharSet = CharSet.Auto)]
internal static extern int SendMessage(IntPtr hWnd, int wMsg, int wParam, int lParam);
}
/// <summary>
/// A Windows progress bar control with Windows Vista & 7 functionality.
/// </summary>
[ToolboxBitmap(typeof(ProgressBar))]
public class Windows7ProgressBar : ProgressBar {
private bool m_showInTaskbar;
private ProgressBarState m_State = ProgressBarState.Normal;
private ContainerControl ownerForm;
public Windows7ProgressBar() {
}
public Windows7ProgressBar(ContainerControl parentControl) {
ContainerControl = parentControl;
}
public ContainerControl ContainerControl {
get {
return ownerForm;
}
set {
ownerForm = value;
if (!ownerForm.Visible) {
((Form)ownerForm).Shown += Windows7ProgressBar_Shown;
}
}
}
public override ISite Site {
get {
return base.Site;
}
set {
// Runs at design time, ensures designer initializes ContainerControl
base.Site = value;
if (value is null) {
return;
}
var service = value.GetService(typeof(IDesignerHost)) as IDesignerHost;
if (service is null) {
return;
}
var rootComponent = service.RootComponent;
ContainerControl = rootComponent as ContainerControl;
}
}
private void Windows7ProgressBar_Shown(object sender, EventArgs e) {
if (ShowInTaskbar) {
if (Style != ProgressBarStyle.Marquee) {
SetValueInTB();
}
SetStateInTB();
} ((Form)ownerForm).Shown -= Windows7ProgressBar_Shown;
}
/// <summary>
/// Show progress in taskbar
/// </summary>
[DefaultValue(false)]
public bool ShowInTaskbar {
get {
return m_showInTaskbar;
}
set {
if (m_showInTaskbar != value) {
m_showInTaskbar = value;
// send signal to the taskbar.
if (ownerForm is object) {
if (Style != ProgressBarStyle.Marquee) {
SetValueInTB();
}
SetStateInTB();
}
}
}
}
/// <summary>
/// Gets or sets the current position of the progress bar.
/// </summary>
/// <returns>The position within the range of the progress bar. The default is 0.</returns>
public new int Value {
get {
return base.Value;
}
set {
base.Value = value;
// send signal to the taskbar.
SetValueInTB();
}
}
/// <summary>
/// Gets or sets the manner in which progress should be indicated on the progress bar.
/// </summary>
/// <returns>One of the ProgressBarStyle values. The default is ProgressBarStyle.Blocks</returns>
public new ProgressBarStyle Style {
get {
return base.Style;
}
set {
base.Style = value;
// set the style of the progress bar
if (m_showInTaskbar && ownerForm is object) {
SetStateInTB();
}
}
}
/// <summary>
/// The progress bar state for Windows Vista & 7
/// </summary>
[DefaultValue(ProgressBarState.Normal)]
public ProgressBarState State {
get {
return m_State;
}
set {
m_State = value;
bool wasMarquee = Style == ProgressBarStyle.Marquee;
if (wasMarquee) {
// sets the state to normal (and implicity calls SetStateInTB() )
Style = ProgressBarStyle.Blocks;
}
// set the progress bar state (Normal, Error, Paused)
Windows7Taskbar.SendMessage(Handle, 0x410, (int)value, 0);
if (wasMarquee) {
// the Taskbar PB value needs to be reset
SetValueInTB();
} else {
// there wasn't a marquee, thus we need to update the taskbar
SetStateInTB();
}
}
}
/// <summary>
/// Advances the current position of the progress bar by the specified amount.
/// </summary>
/// <param name="value">The amount by which to increment the progress bar's current position.</param>
public new void Increment(int value) {
base.Increment(value);
// send signal to the taskbar.
SetValueInTB();
}
/// <summary>
/// Advances the current position of the progress bar by the amount of the System.Windows.Forms.ProgressBar.Step property.
/// </summary>
public new void PerformStep() {
base.PerformStep();
// send signal to the taskbar.
SetValueInTB();
}
private void SetValueInTB() {
if (m_showInTaskbar) {
ulong _maximum = (ulong)(Maximum - Minimum);
ulong _progress = (ulong)(Value - Minimum);
Windows7Taskbar.SetProgressValue(ownerForm.Handle, _progress, _maximum);
}
}
private void SetStateInTB() {
if (ownerForm is null) {
return;
}
var thmState = ThumbnailProgressState.Normal;
if (!m_showInTaskbar) {
thmState = ThumbnailProgressState.NoProgress;
} else if (Style == ProgressBarStyle.Marquee) {
thmState = ThumbnailProgressState.Indeterminate;
} else if (m_State == ProgressBarState.Error) {
thmState = ThumbnailProgressState.Error;
} else if (m_State == ProgressBarState.Pause) {
thmState = ThumbnailProgressState.Paused;
}
Windows7Taskbar.SetProgressState(ownerForm.Handle, thmState);
}
}
}