如何使用 Winform C# 4.5 在任务栏中显示进度

How do you show progress in the Taskbar with Winform C# 4.5

编辑:我不希望它更新、更改或消失。我希望任务栏在 40% 处启动程序,保持这种状态直到它关闭。

我花了很多时间并尝试了很多例子...但运气不好。

为简单起见,如何使用错误颜色显示完成 40%?

这段代码运行但在屏幕上什么都不做,没有错误,只是运行在:

public TaskbarItemInfo taskBar = new TaskbarItemInfo();

然后在一个方法中:

taskBar.ProgressState = System.Windows.Shell.TaskbarItemProgressState.Error;
taskBar.ProgressValue = 0.40;

如果你在下一行断点并查看,它已经设置了值,它们只是在屏幕上做任何事情...

TaskbarItemInfo 本身不做任何事情。它需要在任务栏上显示的 window。请注意,通常从 WPF Window 的实例中获取 TaskbarItemInfo 的实例。 IE。 class 旨在用于 WPF 程序,而不是 Winforms。

对于 Winforms 程序,您可能会发现使用 Windows API Codepack 更实用,如果我没记错的话它支持此 Shell 功能。

您可以使用 WindowsAPICodePack.Taskbar 中的 TaskbarManager class 来设置表单 Window 的任务栏进度,如下所示:

using Microsoft.WindowsAPICodePack.Taskbar;
...
private void Form1_Load(object sender, EventArgs e)
{
    TaskbarManager.Instance.SetProgressState(TaskbarProgressBarState.Error, Handle);
    TaskbarManager.Instance.SetProgressValue(40, 100, Handle);
}

使用当前表单的 .Handle 告诉经理应该向哪个 window 提供此功能。如果您希望在同一个地方处理它的进度,您也可以使用来自另一种形式的 public 静态指针引用。

不幸的是,出于某种原因,尽管该库仍然具有相关性,但 Microsoft 不再为此提供下载。但这里有一个 Whosebug Q&A 和许多其他 links 相同的库:Windows API Code Pack: Where is it?。请注意,有两个版本,1.0 和 1.1。通常,您可能更喜欢 1.1 版本;它有许多错误修复、新增功能和更好的 Fxcop 合规性。我提供的 link 适用于 1.1,但是在那篇 SO 文章中也有 link 用于下载 1.0。

我通过从主框架线程创建一个单独的线程来执行发送进度更新的代码来完成此操作,您可以在进度条上调用 setProgress,但您必须创建一个委托方法,否则您将得到一个运行时异常,你的线程正在访问主线程上的一个控件,这就是我要做的,

在你的 class 中声明一个委托方法,如果你有进度条,

public delegate void SetProgressDelg(int level);

然后实现这个方法来更新你的进度条,

public void SetProgress(int level)
{
      if (this.InvokeRequired)
      {
        SetProgressDelg dlg = new SetProgressDelg(this.SetProgress);
        this.Invoke(dlg, level);
        return;
      } 
      progressBar.Value = level;
}

希望它有用,我在几个应用程序中使用它并且效果很好。

这是构建进度条的方法,

 ToolStripContainer  = toolStripContainer1 = new System.Windows.Forms.ToolStripContainer();
 // StatusBar
 // 
 ToolStripStatusLabel StatusBar = new System.Windows.Forms.ToolStripStatusLabel();
 StatusBar.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Text;
 StatusBar.ForeColor = System.Drawing.Color.Blue;
 StatusBar.LinkColor = System.Drawing.Color.Navy;
 StatusBar.Name = "StatusBar";
 StatusBar.Size = new System.Drawing.Size(732, 20);
 StatusBar.Spring = true;
 StatusBar.Text = "Status Messages Go Here";
 StatusBar.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;
 // 
 // ProgressBar
 // 
 ToolStripProgressBar ProgressBar = new System.Windows.Forms.ToolStripProgressBar();
 ProgressBar.ForeColor = System.Drawing.Color.Yellow;
 ProgressBar.Name = "ProgressBar";
 ProgressBar.Size = new System.Drawing.Size(150, 19);


 // 
 // StatusStrip
 // 
 StatusStrip StatusStrip = new System.Windows.Forms.StatusStrip();
 StatusStrip.Dock = System.Windows.Forms.DockStyle.None;
 StatusStrip.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
 StatusBar, this.ProgressBar});
 StatusStrip.Location = new System.Drawing.Point(0, 0);
 StatusStrip.Name = "StatusStrip";
 StatusStrip.Size = new System.Drawing.Size(899, 25);
 StatusStrip.TabIndex = 0;

 toolStripContainer1.BottomToolStripPanel.Controls.Add(this.StatusStrip);

然后您想将 toolStripContainer 添加到主面板的控件中。

您想从正在处理您的任务的线程调用 SetProgress, 这是你如何开始一个话题,

 //* from your class of your main frame
   //* this is where SetStatus is defined
   //* start a thread to process whatever task 
   //* is being done

   Thread t  = new Thread(StartProc);
   t.Start();


   public void StartProc()
   {
      //* start processing something, 
      //*let's assume your are processing a bunch of files
      List<string> fileNames;
      for (int i = 0; i < fileNames.Count; i++)
      {
         //* process file here
         //* ...........

         //* then update progress bar
         SetProgress((int)((i + 1) * 100 / fileNames.Length));
      }

      //* thread will exit here
    }

如果您还需要什么,请告诉我,希望对您有所帮助,

这是一个简短的示例,您应该可以使用它来满足您的需求:

    System.Windows.Window w = new System.Windows.Window();
    w.TaskbarItemInfo = new System.Windows.Shell.TaskbarItemInfo() { ProgressState = System.Windows.Shell.TaskbarItemProgressState.Normal };
    w.Loaded += delegate {
        Action<Object> callUpdateProgress = (o) => {
            w.TaskbarItemInfo.ProgressValue = (double) o;
        };

        Thread t = new Thread(() => {
            for (int i = 1; i <= 10; i++) {
                w.Dispatcher.BeginInvoke(callUpdateProgress, 1.0 * i / 10);
                Thread.Sleep(1000);
            }
        });
        t.Start();
    };

    System.Windows.Application app = new System.Windows.Application();
    app.Run(w);

要完成上述工作,您需要在顶部添加 using System.Threading; 并添加以下引用:PresentationCorePresentationFrameworkSystemXamlWindowsBase .

尝试:

Microsoft.WindowsAPICodePack.Taskbar.TaskbarManager.Instance.SetProgressState(Microsoft.WindowsAPICodePack.Taskbar.TaskbarProgressBarState.NoProgress);
Microsoft.WindowsAPICodePack.Taskbar.TaskbarManager.Instance.SetProgressValue(ActualValue, MaxValue));

powershell -File ProgressState.ps1

ProgressState.ps1

$code = @"
using System;
using System.Windows;
using System.Threading;

namespace ProgressState
{
    public class Program
    {
        public static void Main()
        {
        
            Console.Write("Progress");
        
            System.Windows.Window w = new System.Windows.Window
            {
                Title = "Loading...",
                Width = 200,
                Height = 200,
                Left = -300
            };
            
            w.TaskbarItemInfo = new System.Windows.Shell.TaskbarItemInfo() { ProgressState = System.Windows.Shell.TaskbarItemProgressState.Normal };
            w.Loaded += delegate {
                Action<Object> callUpdateProgress = (o) => {
                    w.TaskbarItemInfo.ProgressValue = (double) o;
                    if((double) o > 0.9)
                        w.TaskbarItemInfo.ProgressState = System.Windows.Shell.TaskbarItemProgressState.Error;
                };

                Thread t = new Thread(() => {
                    for (int i = 1; i <= 10; i++) {
                        w.Dispatcher.BeginInvoke(callUpdateProgress, 1.0 * i / 10);
                        Console.Write(".");
                        Thread.Sleep(200);
                    }

                    Console.WriteLine("\nFinish");
                    w.Close();
                });
                
                t.Start();
                
            };

            System.Windows.Application app = new System.Windows.Application();
            app.Run(w);
        }
    }
}
"@
 
Add-Type -TypeDefinition $code -ReferencedAssemblies PresentationFramework,PresentationCore,WindowsBase,System.Xaml -Language CSharp    
iex "[ProgressState.Program]::Main()"