LaBouaBouate

Cours PowerShell #8 - Ajout de l'interface graphique

Consigne

Nouveau départ ! On va implémenter une interface graphique réalisée avec Windows Presentation Foundation (WPF) et stockée dans un fichier XAML externe au script. Si vous le souhaitez, vous pouvez faire votre propre interface graphique en utilisant Visual Studio Community par exemple. Je vous recommande tout de même d’utiliser le fichier que je propose comme point de départ.

Dans un premier temps, on va juste vouloir lancer l’interface graphique et laisser le joueur entrer une estimation dans la boite de texte. Lorsque le joueur appuie sur la touchée “Entrée” de son clavier, l’estimation est affichée dans la console et la boite de texte est vidée de son contenu.

Recommandation

Pour cette partie, je vous recommande de créer un nouveau script plutôt qu’adapter le script existant. De cette manière, vous pourrez créer la structure liée à l’interface graphique, puis copier-coller les bouts de code encore pertinents.

Résultat attendu

Démonstration du résultat attendu pour la partie 8

Ressources

Comme cette partie est relativement compliquée, je vous donne quelques ressources :


Étape par étape

  1. Charger l’interface graphique
  2. Créer des variables pour chaque élément de l’interface graphique
  3. Afficher l’interface graphique
  4. Ajouter une action pour la boite de texte

Charger l’interface graphique

Ce bout de code est assez barbare, mais il y a peu de choses à comprendre donc ne vous en faites pas !

Dans un premier temps, on ajoute les prérequis nécessaires à l’affichage de notre interface WPF avec le Add-Type. Une fois ajouté, on s’occupe de récupérer et de stocker le contenu de notre fichier XAML dans la variable globale $xaml. Dans l’exemple, je récupère le XAML via la commande Invoke-WebRequest puisque celui-ci est hébergé sur GitHub. Si vous souhaitez utiliser plutôt un fichier local, vous pouvez utiliser la commande Get-Content.

Une fois que l’on a tous les éléments en main, on peut maintenant utiliser la dernière ligne de notre exemple pour créer un nouvel objet du type interface graphique, stocké dans la variable globale $interface.

À propos des variables globales

Nous sommes obligés d’utiliser des variables du type $Global: car l’interface graphique et la console seront dans deux instances séparées. Sans cette indication d’étendue, les deux instances ne pourront pas communiquer entre elles.

Il ne s’agit bien évidemment pas de connaitre ces commandes par cœur, l’idée est simplement de savoir à quoi elles servent.

Add-Type -AssemblyName PresentationFramework
$uri = "https://raw.githubusercontent.com/leobouard/leobouard.github.io/main/assets/files/interface.xaml"
[xml]$Global:xaml = (Invoke-WebRequest -Uri $uri).Content
$Global:interface = [Windows.Markup.XamlReader]::Load((New-Object System.Xml.XmlNodeReader $xaml))

Créer des variables pour chaque élément de l’interface graphique

Toutes les interactions que le code va avoir avec l’interface graphique vont se faire à travers des variables correspondant à chaque élément. On va donc avoir une variable pour la boite de texte (textbox), une variable pour la barre de progression, des variables pour les étiquettes (label), etc.

On fait donc une boucle du type ForEach-Object pour créer une variable globale pour chaque élément XAML avec un attribut “Name” :

$xaml.SelectNodes("//*[@Name]") | ForEach-Object { 
    Set-Variable -Name ($_.Name) -Value $interface.FindName($_.Name) -Scope Global
}

Afficher l’interface graphique

Une fois que toutes les étapes préliminaires sont terminées, on peut enfin afficher notre interface graphique ! Pour ça, on utilise la méthode ShowDialog() sur la variable qui contient notre interface. Cette commande doit être placée à la dernière ligne de notre script.

Le $null = avant la commande permet d’empêcher d’afficher un résultat dans la console.

$null = $Global:interface.ShowDialog()

Ajouter une action pour la boite de texte

Avec une interface graphique, on va vouloir assigner des actions à certains éléments de l’interface. Par exemple : appuyer sur un bouton va afficher un message dans la console. Dans notre jeu, c’est quand le joueur soumet son chiffre que l’on veut déclencher une action. On pourrait très bien choisir d’assigner ça à un bouton, mais j’ai choisi d’opter pour un déclencheur via la boite de texte : on lance l’action dès que la touche “Entrée” est appuyée.

Pour récupérer la liste de tous les déclencheurs possibles (car les déclencheurs changent selon si il s’agit d’un bouton, d’une liste déroulante, d’une case à cocher…), on utilise la commande PowerShell : Get-Member -MemberType Event. J’ai choisi le déclencheur “KeyDown” qui correspond à une touche appuyée, mais d’autres choix sont possibles.

Pour déclarer une action à faire pour un déclencheur, la syntaxe est la suivante : $textboxResponse.Add_KeyDown({ ... }). Ensuite on ajoute une condition if pour vérifier que la touche qui a été appuyée correspond bien à la touche “Entrée” puis :

  1. On vide le contenu de la boite de texte pour permettre une nouvelle estimation
  2. On affiche l’estimation de l’utilisateur dans la console
$textboxResponse.Add_KeyDown({
    if ($_.Key -eq "Return") {
        $answer = [int]($textboxResponse.Text)
        $textboxResponse.Text = $null
        Write-Host $answer
    }
})

Correction

Voir le script complet

Commentaires