Alessandro Del Sole's Blog

{ A programming space about Microsoft® .NET® }
posts - 1908, comments - 2047, trackbacks - 352

My Links

News

Your host

This is me! Questo spazio è dedicato a Microsoft® .NET®, di cui sono molto appassionato :-)

Cookie e Privacy

Disabilita cookie ShinyStat

Microsoft MVP

My MVP Profile

Microsoft Certified Professional

Microsoft Specialist

Xamarin Certified Mobile Developer

Il mio libro su VB 2015!

Pre-ordina il mio libro su VB 2015 Pre-ordina il mio libro "Visual Basic 2015 Unleashed". Clicca sulla copertina per informazioni!

Il mio libro su WPF 4.5.1!

Clicca sulla copertina per informazioni! E' uscito il mio libro "Programmare con WPF 4.5.1". Clicca sulla copertina per informazioni!

These postings are provided 'AS IS' for entertainment purposes only with absolutely no warranty expressed or implied and confer no rights.
If you're not an Italian user, please visit my English blog

Le vostre visite

I'm a VB!

Guarda la mia intervista a Seattle

Follow me on Twitter!

Altri spazi

GitHub
I miei progetti open-source su GitHub

Article Categories

Archives

Post Categories

Image Galleries

Privacy Policy

Windows 7 e WPF 4: aggiungere pulsanti sulla TaskBar nell'icona dell'applicazione

Windows Presentation Foundation 4, ossia la versione attualmente in Beta 2 che farà parte poi di .NET Framework 4/VS 2010, offre l'integrazione nativa con Windows 7 senza la necessità di dover ricorrere a componenti e librerie esterne (almeno per la maggior parte delle attività). Il multi-touch e l'integrazione con la task bar sono alcune delle funzionalità disponibili.

In questo post ci proponiamo di vedere come sia possibile aggiungere dei pulsanti all'icona che rappresenta l'applicazione nella task bar, un po' come avviene per Windows Media Player, che offre i pulsanti di controllo anche quando passiamo col mouse sopra l'icona:

Prima di proseguire con il codice faccio una piccola premessa. Lo scopo del post non è di introdurre WPF (anzi farò uso di cose più avanzate come i command bindings), quindi darò per scontati un po' di concetti e andrò abbastanza spedito per poi soffermarmi sui concetti inerenti il discorso Windows 7. Detto questo, iniziamo. Lo scopo è ricostruire, anche se con funzionalità ridotte, un lettore multimediale con WPF e Visual Basic 2010 per poi aggiungere tre pulsanti che siano visibili nella task bar. Dopo aver creato il progetto, iniziamo a definirne l'interfaccia in questo modo:

<Window x:Class="MainWindow"

    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

    Title="MainWindow" Height="350" Width="540">

   

    <!--Un semplice sfondo a gradiente -->

    <Window.Background>

        <LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">

            <GradientStop Color="Black" Offset="0" />

            <GradientStop Color="White" Offset="1" />

        </LinearGradientBrush>

    </Window.Background>

    

    <!-- Suddivido la Grid in due righe-->

    <Grid>

        <Grid.RowDefinitions>

            <RowDefinition />

            <RowDefinition Height="50" />

        </Grid.RowDefinitions>

 

        <!-- Nella prima metto il MediaElement (notare

             l'utilizzo del binding per il volume)-->

        <MediaElement Name="Media1" Grid.Row="0" LoadedBehavior="Manual"

                      Volume="{Binding ElementName=VolumeSlider, Path=Value}"

                      MediaFailed="Media1_MediaFailed" >

        </MediaElement>

Ora mi fermo un momento. Lo scopo è avere dei pulsanti di controllo nella finestra dell'applicazione, ma anche sulla task bar. Ciò significa che avremo dei duplicati, pulsanti diversi che fanno la stessa cosa. Possiamo perciò ricorrere alla tecnica del commanding invece che gestire gli eventi Click. In sostanza utilizziamo dei "comandi", astratti dai controlli, che assegneremo ai controlli e che potranno essere eseguiti solo al verificarsi di determinate condizioni. Prima il codice relativo ai pulsanti nella finestra:

        <!-- Una serie di pulsanti

             Notare l'utilizzo dei Command predefiniti -->

        <StackPanel Orientation="Horizontal" Grid.Row="1">

            <Button Name="PlayButton" Width="70" Height="40" Command="MediaCommands.Play"

                    Margin="5" Content="{Binding RelativeSource={RelativeSource Self}, Path=Command.Text}" />

           

            <Button Name="PauseButton" Width="70" Height="40" Command="MediaCommands.Pause"

                    Margin="5"

                    Content="{Binding RelativeSource={RelativeSource Self}, Path=Command.Text}"/>

           

            <Button Name="StopButton" Width="70" Height="40"

                    Margin="5" Command="MediaCommands.Stop"

                    Content="{Binding RelativeSource={RelativeSource Self}, Path=Command.Text}"/>

           

            <Button Name="BrowseButton" Width="40" Height="40"

                    Margin="5" Content="..."/>

            <!-- Imposta il volume-->

            <Slider Name="VolumeSlider" Width="80" Margin="5"

                    Minimum="0" Maximum="1" Value="0.5" TickFrequency="0.1"

                    AutoToolTipPlacement="TopLeft" TickPlacement="BottomRight"/>

           

        </StackPanel>

    </Grid>

WPF, come forse sapete, definisce dei comandi predefiniti per diversi scenari applicativi, evitando di definirne dei propri. I MediaCommands espongono comandi da utilizzare in contesti multimediali come questo. Pertanto la proprietà Command del controllo si assegna col comando desiderato. Poichè i command definiscono anche un testo localizzato da poter mostrare nel controllo, la proprietà Content è in binding con la proprietà Text del comando, che restituisce il testo localizzato. Io uso Windows in inglese, per cui la mia localizzazione sarà comunque Play, Stop, Pause. Ora definiamo i CommandBindings, ossia definiamo i gestori di evento che si associano ai comandi desiderati:

    <!-- Assegno ai comandi i relativi gestori di evento-->

    <Window.CommandBindings>

        <CommandBinding Command="MediaCommands.Play" x:Name="PlayCommand"

                        Executed="PlayCommand_Executed"

                        CanExecute="PlayCommand_CanExecute"/>

        <CommandBinding Command="MediaCommands.Stop" x:Name="StopCommand"

                        Executed="StopCommand_Executed"

                        CanExecute="StopCommand_CanExecute"/>

        <CommandBinding Command="MediaCommands.Pause" x:Name="PauseCommand"

                        Executed="PauseCommand_Executed"

                        CanExecute="PauseCommand_CanExecute"/>

    </Window.CommandBindings>

 

Ciascun CommandBinding definisce che per il tal comando, il gestore Executed si occuperà di eseguire l'azione desiderata mentre il CanExecute verificherà che sia però possibile eseguirla. Il tutto avrà poi un seguito nel codice Visual Basic, ma lo vedremo dopo. Ora viene il bello, ossia l'integrazione con la task bar di Windows 7. Osservate questo codice:

    <Window.TaskbarItemInfo>

        <TaskbarItemInfo Description="Control your media" ThumbnailClipMargin="5">

            <TaskbarItemInfo.ThumbButtonInfos>

                <ThumbButtonInfoCollection>

                    <ThumbButtonInfo x:Name="ThumbPlayButton" Command="MediaCommands.Play"

                                 DismissWhenClicked="False" CommandTarget="{Binding ElementName=PlayButton}"

                                 Description="Play" ImageSource="/MediaPlayer;component/Images/PlayHS.png" />

                   

                    <ThumbButtonInfo x:Name="ThumbStopButton" Command="MediaCommands.Stop"

                                 DismissWhenClicked="False" CommandTarget="{Binding ElementName=StopButton}"

                                 Description="Stop" ImageSource="/MediaPlayer;component/Images/StopHS.png" />

 

                    <ThumbButtonInfo x:Name="ThumbPauseInfo" Command="MediaCommands.Pause"

                                 DismissWhenClicked="False" CommandTarget="{Binding ElementName=PauseButton}"

                                 Description="Pause" ImageSource="/MediaPlayer;component/Images/PauseHS.png" />

 

                </ThumbButtonInfoCollection>

            </TaskbarItemInfo.ThumbButtonInfos>

        </TaskbarItemInfo>

    </Window.TaskbarItemInfo>

</Window>

L'oggetto TaskbarItemInfo ottiene il riferimento all'icona dell'applicazione sulla task bar. La sua proprietà Description consentirà di visualizzare una tooltip al passaggio del mouse, mentre la ThumbnailClipMargin stabilisce il margine per la distanza. Tra i vari elementi che può contenere, ci sono i pulsanti, ossia tanti oggetti ThumButtonInfo (fino a un max di 7) contenuti in una collezione chiamata ThumButtonInfoCollection. Ciascun pulsante funziona essenzialmente come un Button normale, infatti dispone di un evento Click (che però non utilizziamo) oppure di un Command, che andiamo ad assegnare col rispettivo comando come abbiamo fatto coi precedenti. Da notare che questi pulsanti non mostrano testo, ma solo immagini per cui hanno la sola proprietà ImageSource. Ricordatevi chiaramente di specificare le immagini di vostro gradimento, le cui dimensioni devono essere 16 x 16. DismissWhenClicked si usa per evitare che il pulsante sia cliccabile una sola volta. Notate come la proprietà CommandTarget colleghi l'attuale pulsante al corrispondente fratello maggiore sulla finestra. Ora si passa al codice Visual Basic. Anche qui vado spedito e vi rimando alla lettura dei commenti:

Class MainWindow

 

    Private sourceMedia As String = String.Empty

 

    Private Sub BrowseButton_Click(ByVal sender As System.Object,

                                   ByVal e As System.Windows.RoutedEventArgs) Handles BrowseButton.Click

 

        Dim dialog As New Microsoft.Win32.OpenFileDialog

        With dialog

            .Title = "Select a media file"

            .Filter = "Avi & Wmv|*.avi;*.wmv|All files|*.*"

 

            If .ShowDialog = True Then

                Me.sourceMedia = .FileName

                Me.Media1.Source = New Uri(sourceMedia, UriKind.RelativeOrAbsolute)

            End If

        End With

    End Sub

 

 

    'Si attiva nel caso in cui l'apertura del file multimediale fallisca

    Private Sub Media1_MediaFailed(ByVal sender As System.Object,

                                   ByVal e As System.Windows.ExceptionRoutedEventArgs)

        MessageBox.Show(e.ErrorException.Message)

    End Sub

 

    'Esegue le azioni associate ai comandi

    Private Sub PlayCommand_Executed(ByVal sender As System.Object,

                                     ByVal e As System.Windows.Input.ExecutedRoutedEventArgs)

        Me.Media1.Play()

    End Sub

 

    Private Sub StopCommand_Executed(ByVal sender As System.Object,

                                     ByVal e As System.Windows.Input.ExecutedRoutedEventArgs)

        Me.Media1.Stop()

    End Sub

 

    Private Sub PauseCommand_Executed(ByVal sender As System.Object,

                                      ByVal e As System.Windows.Input.ExecutedRoutedEventArgs)

        Me.Media1.Pause()

    End Sub

 

    'Imposto la condizione che, se vera, rende attivi

    'i controlli associati al comando

    Private Sub PlayCommand_CanExecute(ByVal sender As System.Object,

                                       ByVal e As System.Windows.Input.CanExecuteRoutedEventArgs)

        e.CanExecute = Me.Media1.Source IsNot Nothing

    End Sub

 

    Private Sub StopCommand_CanExecute(ByVal sender As System.Object,

                                       ByVal e As System.Windows.Input.CanExecuteRoutedEventArgs)

        e.CanExecute = Me.Media1.Source IsNot Nothing

    End Sub

 

    Private Sub PauseCommand_CanExecute(ByVal sender As System.Object,

                                        ByVal e As System.Windows.Input.CanExecuteRoutedEventArgs)

        e.CanExecute = Me.Media1.Source IsNot Nothing

    End Sub

End Class

Notate semplicemente come i gestori di CanExecute impostino la condizione che, finchè falsa, disabiliterà i controlli dell'interfaccia. Diventerà vera, quindi abilitando i pulsanti, solamente quando selezionerete un file multimediale. Ora avviamo l'applicazione, selezioniamo un file multimediale e... spettacolo:

Abbiamo quindi reso interattiva l'icona che rappresenta la nostra applicazione aggiungendo dei pulsanti che ci permettono di controllare il file in riproduzione, il tutto grazie a WPF 4 e al suo livello di integrazione con Windows 7.

Il codice sorgente è disponibile a questo indirizzo dell'area download di VB T&T e richiede almeno Visual Studio 2010 Express Beta 2.

Alessandro

Print | posted on mercoledì 9 dicembre 2009 00:30 | Filed Under [ Visual Basic Windows Presentation Foundation Windows 7 Visual Studio 2010 ]

Powered by:
Powered By Subtext Powered By ASP.NET