Sottoscrivi il feed di DotNetToscana Seguici su Twitter Unisciti a DotNetToscana su Facebook Seguici su Linkedin

Jump List con Windows Forms

Rate this Content 0 Votes

Livello: Avanzato - Autore: Marco Minerva

Le Jump List sono i menu che compaiono quando si fa clic con il tasto destro del mouse su un'icona nelle barra delle applicazioni di Windows 7 e Windows Server 2008: grazie ad esse, è possibile accedere ai file recenti dell'applicazione e avere scorciatoie per le funzionalità più usate:

Una funzionalità di questo tipo è sicuramente accattivante. Quindi noi, da bravi programmatori, dobbiamo pensare di aggiungerla anche nelle nostri applicazioni.

WPF 4 fornisce un supporto nativo alle Jump List. Se utilizziamo le Windows Form, invece, dobbiamo ricorrere al Windows API Code Pack, una serie di wrapper managed che permette di accedere alle funzionalità dell'API di Windows. Disponibile anche su NuGet, esso mette a disposizione tutto quello che serve per gestire le Jump List nelle nostre applicazioni Windows Forms.

Tuttavia, un grosso limite delle Jump List (indipentemente dalla tecnologia che si utilizza) è che le voci mostrate possono solo avviare programmi, URL o file: non è possibile inviare comandi direttamente all'applicazione a cui la Jump List appartiene.

Per ovviare a questa situazione, ho realizzato una libreria, Jump List Helpers, che sfrutta le funzionalità del Windows API Code Pack e definisce una serie di metodi che facilitano la creazione della Jump List, aggiungendo inoltre la possibilità di ricevere notifiche, mediante il classico meccanismo di eventi, quando si seleziona un comando relativo alla propria applicazione. Come sempre, è disponibile su MSDN Code Gallery e scaricabile direttamente tramite NuGet (con il nome JumpListHelpers):

In questo articolo voglio illustrare alcuni esempi del suo utiizzo.

Dopo aver aggiunto un riferimento alla libreria, abbiamo a disposizione un oggetto di nome JumpListManager, mediante il quale possiamo aggiungere comandi alla lista associata all'applicazione:

  • AddTaskLink
  • AddCategoryLink
  • AddTaskSelfLink
  • AddCategorySelfLink

I primi due consentono di aggiungere comandi che puntano ad applicazioni esterne, URL e file. I numerosi overload disponibili permettono di specificare il nome da mostrare, il percorso del file/URL, gli argomenti associati e l'icona. Con gli ultimi due, invece, possiamo aggiungere comandi che verranno gestiti dalla nostra applicazione (vedremo tra poco come). Inoltre, i metodi che hanno Task nel nome aggiungono voci alla sezione Tasks (Attività in italiano) della Jump List, mentre gli altri consentono di specificare anche il nome della categoria in cui inserirli. 

La Jump List richiede l'esistenza di una finestra visibile a cui associarla, altrimenti si otterrà un errore in fase di creazione.  Di conseguenza, la possiamo define nell'evento Shown del nostro form, generato la prima volta che viene mostrata la finestra:

private void MainForm_Shown(object sender, EventArgs e)
{
    JumpListManager.AddCategorySelfLink("Comandi", "Primo comando", "Comando1");
    JumpListManager.AddCategorySelfLink("Comandi", "Secondo comando", "Comando2");
    JumpListManager.AddCategorySelfLink("Comandi", "Terzo comando", "Comando3");

    JumpListManager.AddCategoryLink("Collegamenti", "DotNetToscana", "http://www.dotnettoscana.org", "shell32.dll", 220);
    JumpListManager.AddCategoryLink("Collegamenti", "Around and About .NET World", "http://blogs.ugidotnet.org/marcom", "shell32.dll", 220);
    
    JumpListManager.AddTaskLink("Avvia Blocco note", "notepad.exe", "notepad.exe");
    JumpListManager.AddTaskLink("Avvia la Calcolatrice", "calc.exe", "calc.exe");
    JumpListManager.AddTaskLink("Avvia Paint", "mspaint.exe", "mspaint.exe");
    
    JumpListManager.Refresh();
}

 Il risultato di questo codice è il seguente:

La Jump List è già funzionante. Se facciamo clic su una delle voci della sezione Attività, sarà avviato il programma corrispondente. Analogamente, un clic su un collegamento avvierà il browser Internet sulla pagina specificata.

Sui primi tre comandi, invece, dobbiamo fare un discorso a parte. Li abbiamo definiti usando il metodo AddCategorySelfLink, perché si riferiscono alla nostra applicazione. Tuttavia, quando li selezioniamo, Windows avvia una nuova istanza del programma, passandogli come argomento i parametri che abbiamo indicato in fase di creazione della Jump List (ovvero Comando1, Comando2 oppure Comando3): come abbiamo detto, infatti, questo è il comportamento predefinito per le Jump List. Quello che vorremmo, invece, è che tali comandi venissero ricevuti dall'istanza attualmente in esecuzione. Per ottenere questo risultato, quando il nostro programma viene avviato, dobbiamo controllare se una sua istanza è già in esecuzione e, in tal caso, inviare ad essa il comando selezionato nella Jump List.

La libreria Jump List Helpers fornisce una serie di metodi ed eventi che rendono estramamente facile realizzare questi controlli.

Dobbiamo innanzi tutto fare alcune modifiche al nostro progetto. Apriamo il file Program.cs e sostituiamo il codice del metodo Main in modo che risulti simile al seguente:

[STAThread]
static void Main()
{
    ProgramManager.Run(typeof(MainForm), "JumpListManager Example");
}

Il metodo ProgramManager.Run prende come argomento il tipo del form principale dell'applicazione (typeof(MainForm) nell'esempio) e il suo titolo. Internamente, verifica se si sta avviando il programma per la prima volta: in caso positivo, esegue lo stesse operazioni del metodo Main originale. Altrimenti, recupera l'istanza esistente e gli passa l'argomento con cui è stata avviata: nel caso dell'avvio tramite Jump List, si tratta proprio del comando che abbiamo impostato in fase di creazione della stessa (nel nostro esempio, Comando1, Comando2 oppure Comando3).

Ora dobbiamo fare in modo che il nostro form riceva questi comandi. Modifichiamo la sua dichiarazione in modo che erediti da JumpListMainFormBase (altra classe contenuta in Jump List Helpers), quindi aggiungiamo un gestore per l'evento JumpListCommandReceived:

public partial class MainForm : JumpListMainFormBase
{
    public MainForm()
    {
        InitializeComponent();

        this.JumpListCommandReceived += new EventHandler(MainForm_JumpListCommandReceived);
    }

    void MainForm_JumpListCommandReceived(object sender, CommandEventArgs e)
    {
        MessageBox.Show("Comando ricevuto: " + e.CommandName, "JumpListManager Example", MessageBoxButtons.OK, MessageBoxIcon.Information); 
    }

    // ...
}

Come il nome lascia intuire, l'evento JumpListCommandReceived viene generato nel momento in cui l'applicazione riceve un comando definito nella Jump List. Esso fornisce un argomento di tipo CommandEventArgs che contiene una sola proprietà, CommandName, attraverso cui possiamo leggere il nome del comando selezionato.

Se proviamo ad eseguire l'applicazione e selezioniamo uno dei tre comandi che abbiamo aggiunto alla Jump List, otterremo questo risultato:

La classe JumpListMainFormBase fornisce anche un altro evento molto utile: StartupInstance, generato nel momento in cui viene avviata un'istanza dell'applicazione:

void MainForm_StarupInstance(object sender, StartupEventArgs e)
{
    var primoAvvio = e.IsFirstInstance;
    var argomenti = e.CommandLineArgs;
}

Esso aggiunge il supporto alla gestione della singola istanza, che Visual Basic .NET fornisce in maniera nativa, mentre in C# non è presente (a meno di non aggiungere un riferimento all'assembly Microsoft.VisualBasic.dll). Il significato delle proprietà dell'oggetto StartupEventArgs è intuitivo. Grazie ad esso, ad esempio, è possibile fare in modo che il doppio clic su un tipo di file gestito dal nostro programma ne determini l'apertura all'interno dell'eventuale istanza già in esecuzione.

Questo evento è necessario, inoltre, per gestire un'altra funzionalità delle Jump List: la possibilità di mostrare l'elenco dei file recenti o quelli aperti più frequentemente dall'applicazione. La libreria Jump List Helpers espone due proprietà con cui decidere cosa visualizzare:

  • ShowRecentFiles
  • ShowFrequentFiles

E' importante ricordare che non è possibile mostrare contemporaneamente i file recenti e quelli frequenti. Di default, le Jump List sono configurate per elencare i file recenti. Abbiamo inoltre a disposizione il metodo JumpList.AddToRecent, con cui possiamo aggiungere il file specificato all'elenco di quelli recenti. Nel momento in cui aggiungiamo queste informazioni alla Jump List, un clic sul nome di un file determinerà l'invocazione del metodo StartupInstance, in cui la proprietà StartupEventArgs.IsFirstInstance vale false e StartupEventArgs.CommandLineArgs contiene il nome del file che selezionato.

E' possibile mostrare i file recenti nella Jump List solo se il relativo tipo è registrato dalla nostra applicazione. Dobbiamo quindi aggiungere la gestione del tipo di file nel Registro di configurazione di Windows. Questa operazione può essere realizzata con il progetto di Setup di Visual Studio, utilizzando il comando Add File Type della sezione File Types Editor.

Da notare che, se viene selezionato un comando della Jump List creato con AddTaskSelfLink oppure AddCategorySelfLink, l'evento StartupInstance non viene generato, perché in questo caso tutta la gestione può essere realizzata nell'evento JumpListCommandReceived.

Questi sono tutti i dettagli necessari per integrare la gestione delle Jump List nelle proprie applicazioni utilizzando la libreria Jump List Helpers. Se siete interessati, potete scaricarla da MSDN Code Gallery oppure, più velocemente, con NuGet.