Premier vrai projet Windows : tu vas construire une fenêtre avec des boutons, des cases à cocher, un champ de texte, et y connecter du code C# pour générer un mot de passe selon les choix de l'utilisateur. L'objectif n'est pas seulement de produire l'app — c'est de comprendre comment une interface graphique et du code se parlent.
C'est un projet ambitieux : tu vas écrire ta première application Windows native, avec une vraie fenêtre, des contrôles cliquables et du code qui réagit à l'utilisateur. Ne te laisse pas impressionner par la longueur de l'énoncé — chaque étape est petite et l'ordre est pensé pour que rien ne te bloque.
L'application à construire s'appelle Générateur de mot de passe. L'utilisateur choisit la longueur souhaitée, coche les types de caractères qu'il veut inclure (minuscules, majuscules, chiffres, caractères spéciaux), clique sur un bouton, et un mot de passe aléatoire s'affiche.
À la fin de ce projet, tu seras capable de :
Label, Button, CheckBox, etc.)Random pour générer un résultat aléatoireVoici à quoi ressemblera ton application une fois terminée :

Six éléments à placer : un titre, un champ pour la longueur, quatre cases à cocher, un bouton Générer, une zone de texte pour le résultat, et un message d'information.
Windows Forms (souvent abrégé WinForms) est la technologie historique de Microsoft pour créer des applications fenêtrées Windows. Elle existe depuis 2002. C'est la plus simple à prendre en main parce qu'elle permet de dessiner ton interface à la souris dans un éditeur visuel — pas besoin d'écrire du XML ni du code pour positionner les contrôles.
Une application WinForms est composée de :
Form — chaque fenêtre est une classe FormButton, Label, TextBox…)C'est le concept central à comprendre. Contrairement à un programme console qui s'exécute ligne par ligne du début à la fin, une application fenêtrée :
On dit que l'application est pilotée par les événements (🇬🇧 event-driven). Cliquer sur le bouton Générer déclenchera l'événement Click, qui appellera la méthode que tu auras écrite.
💡 Cette façon de penser est très différente d'un programme console. Au début, l'idée de "code qui ne s'exécute qu'à la demande" peut surprendre. C'est exactement comme une application mobile : rien ne se passe tant que tu ne touches pas l'écran.
Remplis les champs comme ceci :
| Champ | Valeur |
|---|---|
| Solution name | GenerateurMotDePasse |
| Project name | GenerateurMotDePasseApp |
| Solution directory | un dossier clair (par exemple D:\Projets\C#\) |
| Framework | .NET 8.0 (ou la version utilisée en classe) |
💡 Solution vs Projet : une solution est un conteneur qui peut regrouper plusieurs projets (par exemple : une UI + une bibliothèque + des tests). Ici, on n'a qu'un seul projet, mais Rider impose cette structure — c'est normal.
Clique sur le bouton Run (▶ vert, en haut). Une fenêtre vide s'affiche. Ferme-la.
👉 Si tu vois cette fenêtre vide, tout fonctionne. Tu peux passer à l'étape suivante. Sinon, retourne aux étapes de configuration.
Dans l'explorateur de fichiers de Rider, double-clique sur Form1.cs. Une vue spéciale s'ouvre : c'est le concepteur visuel (🇬🇧 designer) qui te permet de dessiner ta fenêtre.
À droite (ou via le menu View → Toolbox), tu trouves la boîte à outils (🇬🇧 Toolbox) avec tous les contrôles disponibles. Tu vas y piocher.
Glisse-dépose les contrôles suivants sur ta Form1 :
| Contrôle | Rôle dans l'app |
|---|---|
Label |
Le titre de la fenêtre |
Label |
Texte « Longueur : » |
NumericUpDown |
Le champ numérique pour la longueur |
CheckBox × 4 |
Une case par type de caractère |
Button |
Le bouton Générer |
Label |
Texte « Mot de passe : » |
TextBox |
La zone qui affichera le résultat |
Label |
La ligne de message |
Place-les en respectant grossièrement le mockup plus haut. La perfection visuelle peut attendre — on s'en occupe à la fin.
Sélectionne chaque contrôle, puis dans le panneau Properties (à droite), trouve la propriété (Name) et change-la. Sans renommage clair, tu te perdras dans ton propre code dans 5 minutes.
| Contrôle | (Name) |
Autre propriété à régler |
|---|---|---|
| Label titre | lblTitre |
Text = "GÉNÉRATEUR DE MOT DE PASSE" |
| NumericUpDown | numLongueur |
Minimum = 4, Maximum = 64, Value = 12 |
| CheckBox 1 | chkMinuscules |
Text = "Lettres minuscules", Checked = true |
| CheckBox 2 | chkMajuscules |
Text = "Lettres majuscules", Checked = true |
| CheckBox 3 | chkChiffres |
Text = "Chiffres", Checked = true |
| CheckBox 4 | chkSpeciaux |
Text = "Caractères spéciaux" |
| Button | btnGenerer |
Text = "Générer" |
| TextBox | txtResultat |
ReadOnly = true, Font plus grosse |
| Label message | lblMessage |
Text = "" (vide au départ) |
Tu as remarqué les préfixes : lbl pour Label, txt pour TextBox, btn pour Button, chk pour CheckBox, num pour NumericUpDown. Ce n'est pas obligatoire pour le compilateur — c'est une convention qui te permet de voir immédiatement de quel type est un contrôle juste en lisant son nom dans le code.
💡 Sans convention, tu te retrouves avec des
password1,password2,password3et tu ne sais plus lequel est le champ texte, lequel est le label, lequel est la case. Avec convention :txtPassword,lblPassword,chkPassword— zéro ambiguïté.
Avant d'écrire la vraie logique, on fait un test minimal pour s'assurer que le bouton réagit.
Double-clique sur le bouton btnGenerer dans le concepteur. Rider :
btnGenerer_Click dans Form1.csClick du boutonTu vois quelque chose comme :
private void btnGenerer_Click(object sender, EventArgs e)
{
}
Tape dedans :
private void btnGenerer_Click(object sender, EventArgs e)
{
MessageBox.Show("Bouton cliqué !");
}
Lance l'application (▶). Clique sur Générer. Une boîte de dialogue doit apparaître.
💡 Pourquoi ce test ? Parce qu'il isole une seule responsabilité : le bouton réagit-il ? Si oui, on sait que tout le câblage interface↔code fonctionne. Si plus tard ta vraie logique ne marche pas, tu sauras que le problème est dans la logique, pas dans la connexion. C'est une habitude à prendre dans tous tes projets : avancer par petits pas validés.
Remplace le MessageBox.Show par le code suivant :
private void btnGenerer_Click(object sender, EventArgs e)
{
int longueur = (int)numLongueur.Value;
bool inclureMinuscules = chkMinuscules.Checked;
bool inclureMajuscules = chkMajuscules.Checked;
bool inclureChiffres = chkChiffres.Checked;
bool inclureSpeciaux = chkSpeciaux.Checked;
}
numLongueur.Value retourne un decimal (pour pouvoir gérer aussi des valeurs à virgule). On le convertit explicitement en int avec (int)… — c'est un cast.chkMinuscules.Checked est un bool qui vaut true si la case est cochée, false sinon. Pas besoin de conversion.💡 Conseil de méthode : à ce stade, tu peux temporairement ajouter
MessageBox.Show($"Longueur : {longueur}");à la fin de la méthode pour vérifier que la valeur est bien lue. C'est une forme rudimentaire de débogage. Tu retireras la ligne avant de continuer.
L'idée : selon les cases cochées, on assemble une chaîne qui contiendra tous les caractères qu'on autorise à tirer au sort.
string caracteres = "";
if (inclureMinuscules) caracteres += "abcdefghijklmnopqrstuvwxyz";
if (inclureMajuscules) caracteres += "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
if (inclureChiffres) caracteres += "0123456789";
if (inclureSpeciaux) caracteres += "!@#$%&*?";
Après ce bloc, la variable caracteres contient uniquement les caractères que l'utilisateur a autorisés. Si toutes les cases sont cochées, la chaîne fait 71 caractères. Si une seule case est cochée, elle est plus courte. Si aucune case n'est cochée, elle est vide — et c'est un problème qu'on doit gérer.
Si la chaîne caracteres est vide, impossible de générer un mot de passe. Il faut prévenir l'utilisateur avant d'essayer.
if (caracteres == "")
{
MessageBox.Show("Sélectionne au moins un type de caractère.",
"Aucune option choisie",
MessageBoxButtons.OK,
MessageBoxIcon.Warning);
lblMessage.Text = "Erreur : aucune option cochée.";
return;
}
Le return est important : il interrompt la méthode. Sans lui, le code continuerait et planterait à l'étape suivante en essayant de lire un caractère dans une chaîne vide.
💡 Principe à retenir : valide toujours tes entrées avant de t'en servir. Plus tôt tu détectes une situation impossible, plus le message d'erreur est clair pour l'utilisateur.
C'est le cœur de la logique. On va tirer aléatoirement, longueur fois, un caractère dans la chaîne caracteres, et le concaténer au résultat.
Random rnd = new Random();
string motDePasse = "";
for (int i = 0; i < longueur; i++)
{
int index = rnd.Next(caracteres.Length);
motDePasse += caracteres[index];
}
new Random() crée un générateur de nombres aléatoiresrnd.Next(caracteres.Length) retourne un entier entre 0 (inclus) et caracteres.Length (exclu) — exactement la plage des indices valides de la chaînecaracteres[index] extrait le caractère à cet indicemotDePasse += … ajoute ce caractère à la fin du résultatfor répète l'opération longueur fois⚠️ Remarque importante (sécurité réelle) :
Randomest pseudo-aléatoire, pas cryptographiquement sûr. Pour ce projet pédagogique, c'est suffisant. Pour une vraie application qui génère de vrais mots de passe à utiliser, on utiliseraitRandomNumberGeneratorde l'espace de nomsSystem.Security.Cryptography. À garder en tête pour la suite.
txtResultat.Text = motDePasse;
lblMessage.Text = $"Mot de passe de {longueur} caractères généré.";
L'interpolation $"…" permet d'insérer la valeur de longueur directement dans la chaîne. C'est l'équivalent moderne et lisible de la concaténation "… " + longueur + " …".
Récapitulons tout en un seul bloc — c'est ce que tu dois avoir dans Form1.cs :
private void btnGenerer_Click(object sender, EventArgs e)
{
int longueur = (int)numLongueur.Value;
string caracteres = "";
if (chkMinuscules.Checked) caracteres += "abcdefghijklmnopqrstuvwxyz";
if (chkMajuscules.Checked) caracteres += "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
if (chkChiffres.Checked) caracteres += "0123456789";
if (chkSpeciaux.Checked) caracteres += "!@#$%&*?";
if (caracteres == "")
{
MessageBox.Show("Sélectionne au moins un type de caractère.",
"Aucune option choisie",
MessageBoxButtons.OK,
MessageBoxIcon.Warning);
lblMessage.Text = "Erreur : aucune option cochée.";
return;
}
Random rnd = new Random();
string motDePasse = "";
for (int i = 0; i < longueur; i++)
{
int index = rnd.Next(caracteres.Length);
motDePasse += caracteres[index];
}
txtResultat.Text = motDePasse;
lblMessage.Text = $"Mot de passe de {longueur} caractères généré.";
}
Lance ton application. Coche les options, choisis une longueur, clique Générer. Tu dois voir un mot de passe différent à chaque clic.
Vérifie systématiquement les cas suivants avant de considérer ton app comme terminée :
| Test | Résultat attendu |
|---|---|
| Toutes cases cochées, longueur 12 | Mot de passe mixte de 12 caractères |
| Seulement chiffres, longueur 6 | Mot de passe de 6 chiffres |
| Aucune case cochée, clic | Message d'erreur, pas de plantage |
| Longueur 4 | Mot de passe court généré |
| Longueur 64 | Mot de passe long généré |
| Deux clics consécutifs | Deux mots de passe différents |
Pour valider le projet, ton application doit :
Si tu termines tôt ou si tu veux pousser :
Clipboard.SetText(txtResultat.Text);)Entrée pour générerTravaille dans cet ordre, pas autrement :
MessageBox.ShowÀ chaque étape, lance l'application et vérifie. Si ça marche, passe à la suivante. Si ça ne marche pas, ne va pas plus loin — règle le problème immédiatement. Empiler des bugs sans les voir, c'est la recette pour ne plus savoir où chercher.
Réponds par écrit à la question suivante en quelques lignes :
Qu'est-ce qui rend un mot de passe sécurisé ?
Dans ta réponse, explique :
Form), de contrôles posés dessus, et de méthodes C# qui réagissent à des événements.Form1.cs.btn, txt, chk, lbl, num…) est indispensable pour rester lisible.Click pour un bouton).