Bonjour tout le monde,

J'ai un certain nombre d'applications WinForms qui doivent faire un son pour indiquer à l'utilisateur le moment d'exécution de quelque chose.

Ça se fait comme ceci :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
Console.Beep(1800,1000);
avec pour arguments la fréquence du son et sa durée.

En voyant comme code Console.Beep, je me dis qu'un projet écrit uniquement pour émettre des sons doit être de type console.

Que nenni, dans ce type de projet l'instruction n'existe pas.

Est-ce que je me suis pris les pieds quelque part ?

Est-ce que dans ce type de projet il y a un autre moyen d'émettre deux sons différents, ou est-ce qu'il faut déclarer toute l'architecture WinForms pour ne jamais l'utiliser, autrement que pour une unique instruction dans l'espace de noms Console ?

Si je mets mon code dans le Form_Load d'un formulaire réduit en icône, je ne peux pas utiliser ReadKey. Faut-il créer une classe winapi avec GetAsyncKeyState ?

***
Si maintenant pour me débrouiller avec ce que j'ai je mets ça dans un projet WinForms ...
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
        private void Form1_Load(object sender, EventArgs e)
        {
            int esc;
            do
            {
                Console.Beep(1200, 20);
                System.Threading.Thread.Sleep(4980);
                Console.Beep(1800, 20);
                System.Threading.Thread.Sleep(4980);
                esc = winapi.GetAsyncKeyState(Keys.Escape);
                Console.Write(esc.ToString());
            } while (esc != 1);
            timer1.Enabled = true;
            this.Focus();
        }
En mode débogage depuis Visual Studio ça marche impec, le bouton affiche "fin de programme", l'utilisateur n'a plus qu'à appuyer sur Entrée (ou espace si il préfère).

Mais si j'ancre le programme dans la barre des tâches, pour pouvoir le lancer sans Visual Studio, les bips c'est OK, mais une fois le formulaire affiché, il ne prend pas le focus, malgré "this.Focus()".

Alors j'insiste, c'est d'ailleurs pour ça que j'ai mis un timer :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
        private void timer1_Tick(object sender, EventArgs e)
        {
            this.Enabled = true;
            Console.Beep(100, 10);
            IntPtr hWnd = winapi.FindWindow(null, "Bips séquentiels");
 
            winapi.SetForegroundWindow(hWnd);
            winapi.SetActiveWindow(hWnd);
            winapi.SetFocus(hWnd);
            //this.Focus();
        }
J'entends les bips mais le formulaire n'est pas sélectionné.

En première intention j'ai mis this.Handle, et comme le formulaire n'était pas sélectionné je me suis dit il doit y avoir une astuce, alors j'ai utilisé FindWindow, avec l'intitulé du formulaire.

Et il ne se sélectionne toujours pas.

Pendant que je suis là je note une curiosité au sujet de FindWindow.
En premier argument, il faut mettre null sinon on ne trouve pas la fenêtre (en tout cas, sous Visual Studio). Si je mets null, j'ai un soulignement dessus pour me signaler l'erreur CS8625, impossible de convertir un littéral ayant une valeur nulle, en type référence non nullable.
La tentation est de mettre Nullable<string> pour le premier argument dans la déclaration de l'API, mais ça coince, il lui faut un String.
Dans l'appel je peux mettre une chaîne vide pour le premier argument, mais alors ça retourne 0 (je crois bien que ça se dit IntPtr.Zero), ce qui ne sert donc à rien.
Alors je laisse null, le compilateur râle mais le boulot est fait. Enfin ... Du moins, sous Visual Studio, il trouve bien une valeur pour le IntPtr.

Dieu sait pourtant que j'ai utilisé cette fonction, et là j'ai oublié comment s'en sortir sans tricher.

***
Je m'en suis sorti en ajoutant ça dans le timer :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
            timer1.Enabled = false;
            SendKeys.Send("%{tab}");
Mais que ça n'empêche pas celui qui trouvera quelque chose de plus élégant de le dire ...
Et aussi celui qui comprend pourquoi j'ai dû faire ça de le dire.