André Alves de Lima

Talking about Software Development and more…

WPF – Notificando progresso na Taskbar do Windows 7

[Atenção!!! Este artigo tem sua versão em vídeo! Se quiser pular a parte escrita e só assistir o vídeo, dê uma olhada no final do post!]

Olá pessoal!

Com o artigo de hoje iniciarei uma série que abordará a utilização das funcionalidades da barra de tarefas do Windows 7 em nossas aplicações WPF, utilizando a API que foi disponibilizada no .NET Framework 4. Esse primeiro artigo da série explicará como podemos mostrar o progresso de alguma atividade na taskbar do Windows 7.

Primeiramente, iniciemos criando uma WPF Application. Para construir o exemplo utilizei o Visual Studio 2010 com .NET Framework 4.

Na nossa MainWindow, vamos configurar o Grid criando 2 RowDefinitions e 2 ColumnDefinitions para dispormos os nossos controles, que serão: um TextBox, um Button e uma ProgressBar. Para isso, utilize o seguinte XAML:

Feito isso, a interface da nossa aplicação vai ficar parecida com esta:

Como você deve ter percebido, a ideia da nossa aplicação é que o usuário digite uma URL no TextBox e clique no Button para fazer o download do arquivo indicado. O progresso do download deverá ser exibido na nossa ProgressBar. Uma vez que essa parte estiver funcionando, vamos incluir o código para refletir o progresso da nossa ProgressBar da Window na taskbar do Windows 7.

O próximo passo, então, é implementarmos o código para fazer o download do arquivo e mostrar o progresso na ProgressBar da nossa Window. Para isso, vamos incluir um handler para o evento Click do nosso Button:

Já no nosso code behind, vamos implementar a lógica para fazer o download do arquivo, utilizando a classe WebClient:

private void btDownload_Click(object sender, RoutedEventArgs e)
{
    WebClient wc = new WebClient();
    wc.DownloadProgressChanged += new DownloadProgressChangedEventHandler(wc_DownloadProgressChanged);
    wc.DownloadFileCompleted += new System.ComponentModel.AsyncCompletedEventHandler(wc_DownloadFileCompleted);
    wc.DownloadFileAsync(new Uri(textURL.Text), System.IO.Path.GetFileName(textURL.Text));
}

void wc_DownloadFileCompleted(object sender, System.ComponentModel.AsyncCompletedEventArgs e)
{
    MessageBox.Show("Download finalizado!");
    progressBar.Value = 0;
}

public void wc_DownloadProgressChanged(Object sender, DownloadProgressChangedEventArgs e)
{
    progressBar.Value = e.ProgressPercentage;
}

Por padrão, não temos a referência a System.Net (onde a classe WebClient está localizada), então, adicione um using apontando para System.Net para que o código acima funcione corretamente.

Feito isso, a nossa aplicação já faz o download do arquivo de forma assíncrona, mostrando o progresso na barra da nossa Window. Vamos, agora, incluir o código para que o progresso seja reportado também na taskbar do Windows 7.

O primeiro passo é incluir na nossa Window uma TaskbarItemInfo:

Aí é só incluirmos a parte de atualização da TaskBar no nosso code behind (as partes incluídas estão com comentário indicativo):

private void btDownload_Click(object sender, RoutedEventArgs e)
{
    // Progresso na taskbar do Windows 7:
    TaskbarItemInfo.ProgressState = System.Windows.Shell.TaskbarItemProgressState.Normal;

    WebClient wc = new WebClient();
    wc.DownloadProgressChanged += new DownloadProgressChangedEventHandler(wc_DownloadProgressChanged);
    wc.DownloadFileCompleted += new System.ComponentModel.AsyncCompletedEventHandler(wc_DownloadFileCompleted);
    wc.DownloadFileAsync(new Uri(textURL.Text), System.IO.Path.GetFileName(textURL.Text));
}

void wc_DownloadFileCompleted(object sender, System.ComponentModel.AsyncCompletedEventArgs e)
{
    MessageBox.Show("Download finalizado!");
    progressBar.Value = 0;
    // Progresso na taskbar do Windows 7:
    TaskbarItemInfo.ProgressValue = 0;
    TaskbarItemInfo.ProgressState = System.Windows.Shell.TaskbarItemProgressState.None;
}

public void wc_DownloadProgressChanged(Object sender, DownloadProgressChangedEventArgs e)
{
    progressBar.Value = e.ProgressPercentage;
    // Progresso na taskbar do Windows 7:
    TaskbarItemInfo.ProgressValue = progressBar.Value / 100;
}

Note que a faixa de valores da ProgressBar da nossa Window vai de zero até cem, a mesma faixa de valores retornada pelo ProgressPercentage do objeto WebClient. Já a taskbar do Windows 7 aceita somente valores de zero até um, portanto, temos que fazer uma divisão do valor da ProgressPercentage do WebClient por cem para que o valor fique na faixa necessária.

Com isso ajustado, temos a taskbar do Windows 7 apresentando o progresso idêntico ao progresso apresentado na ProgressBar da Window.

Quero mostrar agora como poderíamos fazer com que essa alteração fosse indicada diretamente no XAML da Window. Para isso, vamos configurar um Binding para a propriedade ProgressValue do TaskbarItemInfo, apontando para a propriedade Value da ProgressBar da nossa Window.

Só que como temos que fazer uma divisão do valor do Value da ProgressBar por cem, temos que criar primeiramente um ValueConverter para podermos utilizar no nosso binding. Para tanto, inclua o código abaixo no code behind da sua Window:

public class ProgressConverter : IValueConverter
{
    #region IValueConverter Members

    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        return System.Convert.ToDouble(value) / 100;
    }

    public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        return System.Convert.ToDouble(value) * 100;
    }

    #endregion
}

Feito isso precisamos agora criar um StaticResource contendo uma instância do nosso ProgressConverter e aí já podemos também configurar o Binding do TaskbarItemInfo.ProgressValue, como podemos ver no XAML abaixo:

Após isso, podemos então remover o código que atribui o progresso ao nosso TaskbarItemInfo do code behind, já que ele será tratado diretamente no XAML. Portanto, o code behind da nossa Window deve ficar da seguinte forma:

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
    }

    private void btDownload_Click(object sender, RoutedEventArgs e)
    {
        TaskbarItemInfo.ProgressState = System.Windows.Shell.TaskbarItemProgressState.Normal;

        WebClient wc = new WebClient();
        wc.DownloadProgressChanged += new DownloadProgressChangedEventHandler(wc_DownloadProgressChanged);
        wc.DownloadFileCompleted += new System.ComponentModel.AsyncCompletedEventHandler(wc_DownloadFileCompleted);
        wc.DownloadFileAsync(new Uri(textURL.Text), System.IO.Path.GetFileName(textURL.Text));
    }

    void wc_DownloadFileCompleted(object sender, System.ComponentModel.AsyncCompletedEventArgs e)
    {
        MessageBox.Show("Download finalizado!");
        progressBar.Value = 0;
        TaskbarItemInfo.ProgressState = System.Windows.Shell.TaskbarItemProgressState.None;
    }

    public void wc_DownloadProgressChanged(Object sender, DownloadProgressChangedEventArgs e)
    {
        progressBar.Value = e.ProgressPercentage;
    }
}

public class ProgressConverter : IValueConverter
{
    #region IValueConverter Members

    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        return System.Convert.ToDouble(value) / 100;
    }

    public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        return System.Convert.ToDouble(value) * 100;
    }

    #endregion
}

Pronto! Com isso temos o progresso da taskbar do Windows 7 sincronizado com o progresso da ProgressBar na nossa Window!

Como vocês devem ter reparado, ao iniciar o download do arquivo, nós alteramos a propriedade ProgressState do TaskbarItemInfo para Normal. Como o próprio nome diz, isso faz com que a taskbar mostre o progresso da forma padrão (mostrando o progresso em verde). Existem também outros tipos de progresso que você pode utilizar, é só escolher o que melhor se adequa à sua necessidade e utilizar. Abaixo mostro uma figura com cada um dos tipos de ProgressState disponíveis (além do None, que, obviamente, deixa o ícone sem reportar progresso algum):


Normal: Progresso exibido continuamente na cor verde


Error: Progresso exibido continuamente na cor vermelha


Paused: Progresso exibido continuamente na cor amarela


Indeterminate: Progresso exibido na cor verde “pulsando”

É isso aí pessoal! Espero que com esse artigo vocês tenham conseguido entender como podemos reportar progressos na taskbar do Windows 7. Abaixo vocês podem assistir o vídeo que mostra um passo-a-passo do conteúdo apresentado no artigo:

[Observação: para assistir o vídeo em uma qualidade melhor, clique no botão HD do Media Player abaixo]

Até a próxima!

André Alves de Lima.

5 thoughts on “WPF – Notificando progresso na Taskbar do Windows 7

Deixe uma resposta

O seu endereço de e-mail não será publicado. Campos obrigatórios são marcados com *