17 01 2011
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.
WPF – Calendar Control WPF – Criando Jumplists na Taskbar do Windows 7
[…] ATENÇÃO!!! ESTE BLOG MUDOU DE ENDEREÇO: http://www.andrealveslima.com.br VISITE ESTE MESMO POST NO NOVO ENDEREÇO AQUI […]
Olá, parabéns pelo artigo, e pergunta… tem como disponibilizar este exemplo (fonte)
Obrigado!
Cristiano
Olá Cristiano, obrigado pelo comentário.
Este artigo é bem antigo, mas, consegui encontrar os fontes aqui e coloquei-os no seguinte link:
http://andrealveslima.com.br/files/artigos/wpftaskbarw7progress/NotificandoProgressoTaskbarWindows7.zip
André Lima
Bom dia André, tudo bem?
Seria interessante criar um post sobre as diferença, uma especie de comparativo e aplicações das ferramentas:
task vs async vs thread vs backgroundworker
Tenho particularmente não sei qual usar em qual ocasião.
Obrigado e um grande abraço.
Fala André, tudo beleza? Eu sinceramente não sei as diferenças entre eles, vou ter que pesquisar.. Vou colocar aqui na minha lista e, assim que possivel, eu escrevo um artigo e te aviso.. Abraço!