How do you show progress in the Taskbar with Winform C# 4.5 [duplicate]
Asked Answered
B

5

11

EDIT: I don't want it to update, change or go away. I ONLY want the taskbar to be at 40% to start the program, stay that way till it closes.

I spent a lot of hours and tried many examples...but no luck.

To keep it simple, how do you show 40% done in Error color?

This code runs but does nothing on the screen, no errors, just runs right by:

public TaskbarItemInfo taskBar = new TaskbarItemInfo();

then in a method:

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

If you breakpoint on the next line and look, it has set the values, they just don't do anything on the screen...

Braynard answered 8/2, 2015 at 6:13 Comment(1)
For people comming here that don't want to use external dependencies, go here: https://mcmap.net/q/263599/-windows-7-progress-bar-in-taskbar-in-c/9867451Kery
B
6

Here's a short example that you should be able to use to tailor to your needs:

    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);

To make the above work you need to have using System.Threading; at top and also add references of: PresentationCore, PresentationFramework, SystemXaml, WindowsBase.

Bra answered 8/2, 2015 at 8:3 Comment(5)
says it doesnt know what Dispatcher isBraynard
Make sure Window is System.Windows.Window. It's been there since .NET30: msdn.microsoft.com/en-us/library/…Bra
thanks to Loathing for putting this up. Thanks to Faljbour for all the effort. to make the above work you need to have "using System.Threading;" at top and also add references of: PresentationCore, PresentationFramework, SystemXaml, WindowsBase.Braynard
This is a great little snippet. I removed the Thread.Sleep(1000) since i have a progress bar feeding it and it shows perfectly.Sackville
Note that this doesn't work with regular Windows FormsOrthohydrogen
C
10

TaskbarItemInfo doesn't do anything by itself. It needs a window which is represented on the taskbar. Note that one normally gets an instance of TaskbarItemInfo from an instance of a WPF Window. I.e. that class is intended for use in WPF programs, not Winforms.

For a Winforms program, you may find it is more practical to use the Windows API Codepack, which if I recall correctly has support for this Shell feature.

You can use the TaskbarManager class in WindowsAPICodePack.Taskbar to set the Form Window's task bar progress like this:

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

Using the current Form's .Handle to tell the manager to which window this feature should be provided. You can use a public static pointer reference from another form, too, if you wish to handle its progress in the same place.

Unfortunately, for some reason Microsoft is no longer hosting a download for this, in spite of the continued relevance for the library. But here is a StackOverflow Q&A with numerous other links for the same library: Windows API Code Pack: Where is it?. Note that there are two versions, 1.0 and 1.1. In general, you will likely prefer the 1.1 version; it has numerous bug fixes, added features, and much better Fxcop compliance. The link I've provided is for 1.1, but there are links for downloading 1.0 on that SO article as well.

Catechize answered 8/2, 2015 at 6:32 Comment(0)
B
6

Here's a short example that you should be able to use to tailor to your needs:

    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);

To make the above work you need to have using System.Threading; at top and also add references of: PresentationCore, PresentationFramework, SystemXaml, WindowsBase.

Bra answered 8/2, 2015 at 8:3 Comment(5)
says it doesnt know what Dispatcher isBraynard
Make sure Window is System.Windows.Window. It's been there since .NET30: msdn.microsoft.com/en-us/library/…Bra
thanks to Loathing for putting this up. Thanks to Faljbour for all the effort. to make the above work you need to have "using System.Threading;" at top and also add references of: PresentationCore, PresentationFramework, SystemXaml, WindowsBase.Braynard
This is a great little snippet. I removed the Thread.Sleep(1000) since i have a progress bar feeding it and it shows perfectly.Sackville
Note that this doesn't work with regular Windows FormsOrthohydrogen
N
1

I have done this by creating a separate thread from you main frame thread to execute the code that sends out the progress update, where you can call setProgress on your progress bar, but you must create a delegate method otherwise you will get a runtime exception that your thread is accessing a control on the main thread, here is what i would do,

declare a delegate method in your the class were you have the progress bar,

public delegate void SetProgressDelg(int level);

Then implement this method to update your progress bar,

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

hope this works for, I use this in several applications and it works great.

Here is how you build the progress bar,

 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);

then you want to add the toolStripContainer to you controls of the main panel.

you want to call SetProgress from the thread that is processing your task, here is how you start a thread,

 //* 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
    }

Let me know if you need something else, hope this helps,

Notarize answered 8/2, 2015 at 6:36 Comment(5)
how do i set up "progressBar" ? is that setup some how with System.Windows?Braynard
If you are using Visual Studio, then you can get Visual Studio to do all the work for you. But I usually use a ToolStripContainer which has top, bottom and left and right container. The top for a toolbar and the bottom for a status bar. I usually put a statusstrip at the bottom panel of the toolstrip container, then add statusbar and a progressbar. I edit update my answer with some more code.Notarize
and i also need to set it up in another thread too i think? sorry about this, i guess i need the whole solution... i have tried about 8 different partials, also tried many variations of combining partials. :-)Braynard
sure, let me update the answer again, if you want a complete example, I can send you some code if you give me your emailNotarize
thanks for all help here. i took off the first = sign in above and also the two this statements so it would compile. it still cant find ProgressBar, also i am thinking this will be a baron my form and not the taskbar?Braynard
E
-1

try:

Microsoft.WindowsAPICodePack.Taskbar.TaskbarManager.Instance.SetProgressState(Microsoft.WindowsAPICodePack.Taskbar.TaskbarProgressBarState.NoProgress);
Microsoft.WindowsAPICodePack.Taskbar.TaskbarManager.Instance.SetProgressValue(ActualValue, MaxValue));
Empty answered 6/5, 2020 at 12:0 Comment(0)
M
-1

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()"
Microprint answered 19/4, 2021 at 19:22 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.