如果你注意到在Windows 7 beta中,当你复制文件或进行其他系统操作时,任务栏上的Windows资源管理器图标会填充一个类似于表单进度条的绿色进度条。那么,在我的C#表单中,是否有一种方法可以强制我的任务栏进度条与我正在执行的任何任务的进度匹配?转换、传输、生成等都可以使用这个进度条。
如果你注意到在Windows 7 beta中,当你复制文件或进行其他系统操作时,任务栏上的Windows资源管理器图标会填充一个类似于表单进度条的绿色进度条。那么,在我的C#表单中,是否有一种方法可以强制我的任务栏进度条与我正在执行的任何任务的进度匹配?转换、传输、生成等都可以使用这个进度条。
我只是想在我的WinForms应用程序中添加一些任务栏进度动画,而不必下载代码包或切换到WPF以使用TaskbarItemInfo。
解决方案是使用ITaskbarList3接口的类:
using System;
using System.Runtime.InteropServices;
public static class TaskbarProgress
{
public enum TaskbarStates
{
NoProgress = 0,
Indeterminate = 0x1,
Normal = 0x2,
Error = 0x4,
Paused = 0x8
}
[ComImport()]
[Guid("ea1afb91-9e28-4b86-90e9-9e9f8a5eefaf")]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
private 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
[PreserveSig]
void SetProgressValue(IntPtr hwnd, UInt64 ullCompleted, UInt64 ullTotal);
[PreserveSig]
void SetProgressState(IntPtr hwnd, TaskbarStates state);
}
[ComImport()]
[Guid("56fdf344-fd6d-11d0-958a-006097c9a090")]
[ClassInterface(ClassInterfaceType.None)]
private class TaskbarInstance
{
}
private static ITaskbarList3 taskbarInstance = (ITaskbarList3)new TaskbarInstance();
private static bool taskbarSupported = Environment.OSVersion.Version >= new Version(6, 1);
public static void SetState(IntPtr windowHandle, TaskbarStates taskbarState)
{
if (taskbarSupported) taskbarInstance.SetProgressState(windowHandle, taskbarState);
}
public static void SetValue(IntPtr windowHandle, double progressValue, double progressMax)
{
if (taskbarSupported) taskbarInstance.SetProgressValue(windowHandle, (ulong)progressValue, (ulong)progressMax);
}
}
使用起来非常简单的示例:
TaskbarProgress.SetState(this.Handle, TaskbarProgress.TaskbarStates.Indeterminate);
or
TaskbarProgress.SetValue(this.Handle, 50, 100);
TaskbarProgress.SetState(this.Handle, TaskbarProgress.TaskbarStates.Error);
对于那些想跳过阅读文档直接使用的人...
Microsoft.WindowsAPICodePack.dll
Microsoft.WindowsAPICodePack.Shell.dll
--
int max = 100;
var prog = Microsoft.WindowsAPICodePack.Taskbar.TaskbarManager.Instance;
prog.SetProgressState(Microsoft.WindowsAPICodePack.Taskbar.TaskbarProgressBarState.Normal);
for(int i=0;i<max;i++) {
prog.SetProgressValue(i, max);
Thread.Sleep(100);
}
prog.SetProgressState(Microsoft.WindowsAPICodePack.Taskbar.TaskbarProgressBarState.NoProgress);
查看适用于Microsoft .Net Framework的Windows API Code Pack。
您可以访问此链接。
您只需要在表单中添加调用新表单属性的代码,即可更新图标。(为什么要在表单中添加API调用、过程和枚举,如果可以避免呢?)
将以下代码放入项目的新类模块中。
using System.ComponentModel;
using System.Drawing;
using System.Runtime.InteropServices;
namespace System.Windows.Forms
{
[ToolboxBitmap(typeof(Form))]
public class ProgressForm : Form
{
private ThumbnailProgressState m_State = ThumbnailProgressState.NoProgress;
private int m_Maximum = 100;
private int m_Value = 0;
//
// Summary:
// Gets or sets the state in which progress should be indicated on the task
// bar.
//
// Returns:
// One of the System.Windows.Forms.ThumbnailProgressState values. The default is System.Windows.Forms.ThumbnailProgressState.NoProgress
//
// Exceptions:
// T:System.ComponentModel.InvalidEnumArgumentException:
// The value is not a member of the System.Windows.Forms.ThumbnailProgressState enumeration.
//
// History:
// An old Microsoft article
// July 2022 - Verified with Win10, reworded/reformatted ThumbnailProgressState.
// Argument exception of property Value is more granular.
// Windows7orGreater - no longer relevant, but unchanged in case there is a need to distinguish versions beyond Windows 10
//
// Usage:
// Add class with this code to your project
// Add the inheritance "ProgressForm" to the form that will show progress.
// Example: public partial class Form1 : ProgressForm
//
[Browsable(true)]
[DefaultValue(ThumbnailProgressState.NoProgress)]
[EditorBrowsable(EditorBrowsableState.Always)]
public ThumbnailProgressState State
{
get { return m_State; }
set
{
switch (value)
{
case ThumbnailProgressState.NoProgress:
case ThumbnailProgressState.Indeterminate:
case ThumbnailProgressState.Normal:
case ThumbnailProgressState.Error:
case ThumbnailProgressState.Paused:
m_State = value;
OnStateChanged(new EventArgs());
break;
default:
throw new InvalidEnumArgumentException("The value is not a member of the System.Windows.Forms.ThumbnailProgressState enumeration.");
}
}
}
//
// Summary:
// Gets or sets the current position of the progress bar.
//
// Returns:
// The position within the range of the progress bar. The default is 0.
//
// Exceptions:
// T:System.ArgumentException:
// • The value specified is greater than the value of the System.Windows.Forms.ProgressForm.Maximum property.
// • The value specified is less than 0.
[Browsable(true)]
[DefaultValue(0)]
[EditorBrowsable(EditorBrowsableState.Always)]
public int Value
{
get { return m_Value; }
set
{
if (value > m_Maximum)
{
throw new ArgumentException("The value specified is greater than the value of the System.Windows.Forms.ProgressForm.Maximum property.");
}
else if(value < 0)
{
throw new ArgumentException("The value specified is less than 0.");
}
else
{
m_Value = value;
OnValueChanged(new EventArgs());
}
}
}
//
// Summary:
// Gets or sets the maximum value of the range of the control.
//
// Returns:
// The maximum value of the range. The default is 100.
//
// Exceptions:
// T:System.ArgumentException:
// The value specified is less than 0.
[Browsable(true)]
[DefaultValue(100)]
[EditorBrowsable(EditorBrowsableState.Always)]
public int Maximum
{
get { return m_Maximum; }
set
{
if (value < 0)
{
throw new ArgumentException("The value specified is less than 0.");
}
else
{
m_Maximum = value;
if (value < m_Value) m_Value = value;
OnMaximumChanged(new EventArgs());
}
}
}
protected virtual void OnStateChanged(EventArgs e)
{
if (Windows7orGreater) SetProgressState();
}
protected virtual void OnValueChanged(EventArgs e)
{
if (Windows7orGreater) SetProgressValue();
}
protected virtual void OnMaximumChanged(EventArgs e)
{
if (Windows7orGreater) SetProgressValue();
}
protected override void WndProc(ref Message m)
{
if (Windows7orGreater)
{
// if taskbar button created or recreated, update progress status
if (m.Msg == WM_TaskbarButtonCreated) SetProgressState();
}
base.WndProc(ref m);
}
private void SetProgressState()
{
// must be Windows7orGreater
TaskbarList.SetProgressState(Handle, m_State);
SetProgressValue();
}
private void SetProgressValue()
{
switch (m_State)
{
case ThumbnailProgressState.Normal:
case ThumbnailProgressState.Error:
case ThumbnailProgressState.Paused:
TaskbarList.SetProgressValue(Handle, (ulong)m_Value, (ulong)m_Maximum);
break;
}
}
private static int WM_TaskbarButtonCreated = -1;
private static int _winVersion = -1;
internal static bool Windows7orGreater
{
get
{
if (_winVersion < 0)
{
Version osVersion = Environment.OSVersion.Version;
if ((osVersion.Major == 6 && osVersion.Minor > 0) || (osVersion.Major > 6))
{
// Taskbar progress indicator requires Windows 7 Or Greater
_winVersion = 1;
// register taskbar creation window message
WM_TaskbarButtonCreated = RegisterWindowMessage(@"TaskbarButtonCreated");
}
else
{
_winVersion = 0;
}
}
return (_winVersion > 0);
}
}
private static ITaskbarList3 _taskbarList = null;
internal static ITaskbarList3 TaskbarList
{
get
{
if (_taskbarList == null)
{
lock (typeof(ProgressForm))
{
if (_taskbarList == null)
{
_taskbarList = (ITaskbarList3)new CTaskbarList();
_taskbarList.HrInit();
}
}
}
return _taskbarList;
}
}
[DllImport("user32.dll")]
internal static extern int RegisterWindowMessage(string message);
[ComImportAttribute()]
[GuidAttribute("ea1afb91-9e28-4b86-90e9-9e9f8a5eefaf")]
[InterfaceTypeAttribute(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, UInt64 ullCompleted, UInt64 ullTotal);
void SetProgressState(IntPtr hwnd, ThumbnailProgressState tbpFlags);
}
[GuidAttribute("56FDF344-FD6D-11d0-958A-006097C9A090")]
[ClassInterfaceAttribute(ClassInterfaceType.None)]
[ComImportAttribute()]
internal class CTaskbarList { }
}
public enum ThumbnailProgressState
{
/// <summary>
/// No progress is displayed.<br>
/// yourFormName.Value is ignored.</br> </summary>
NoProgress = 0,
/// <summary>
/// Normal progress is displayed.<br>
/// The bar is GREEN.</br> </summary>
Normal = 0x2,
/// <summary>
/// The operation is paused.<br>
/// The bar is YELLOW.</br></summary>
Paused = 0x8,
/// <summary>
/// An error occurred.<br>
/// The bar is RED.</br> </summary>
Error = 0x4,
/// <summary>
/// The progress is indeterminate.<br>
/// Marquee style bar (constant scroll).</br> </summary>
Indeterminate = 0x1
}
}
ProgressForm
添加到需要显示进度的表单中:public partial class Form1 : ProgressForm
if (this.State == ThumbnailProgressState.NoProgress)
{
// Show the progress with GREEN
this.State = ThumbnailProgressState.Normal;
}
this.Maximum = 512; // set to any integer above zero (defaults to 100)
this.Value = 0; // Visually equivalent to this.State = ThumbnailProgressState.NoProgress;
this.Value = 256; // 50% solid GREEN overlay
this.State = ThumbnailProgressState.Error; // Still 50% but now solid RED overlay
this.State = ThumbnailProgressState.Paused; // Still 50% but now solid YELLOW overlay
this.Value = 384; // 75% YELLOW overlay (384 / 512 == 75%)
this.Value = this.Maximum; // 100% YELLOW overlay (512 of 512)
this.State = ThumbnailProgressState.Indeterminate; // Marquee. (Ignores Value and constantly scrolls with a fade)
this.State = ThumbnailProgressState.NoProgress; // Ignores Value, there is no overlay
Imports Microsoft.WindowsAPICodePack
Imports Microsoft.WindowsAPICodePack.Taskbar
// ...
TaskbarManager.Instance.SetProgressValue(X, 100)
其中 X 是您想要显示的进度。