Bonjour bonsoir, mesdames et messieurs, grands, moyens, petits, beaux, moins beaux, pas beaux, gentils, méchants, faux-méchants comme Kylo Ren  , cette introduction commence à devenir beaucoup trop longue et lourde. (cmb)  
 
Vous êtes sur mon tutoriel pour apprendre à développer un lanceur pour Minecraft pour ses dernières versions (1.7 et supérieur, je pense), presque à partir de zéro. 
 
Je dis presque, car je ne vais pas expliquer toutes les notions, raisons pour laquelle je vous conseille d'aller voir le tutoriel dont je vais parler plus bas. 
Je vous souhaite une bonne lecture :) 
 
I.  Introduction 
II.  Les bases 
a .  Mise au point 
b . Les outils nécessaires 
   
III.  Création du projet 
a .   Réglages du projet 
b . Derniers réglages avant de commencer 
  
IV.  Optionnel  - déboguer plus facilement 
a . Préparation de la classe 
b . Premier débogage 
  
V.  La classe LauncherVariables 
VI . Les graphismes 
a . Les choses à éviter 
b . L'image de fond 
c . Les polices d'écriture personnalisées 
1 . Téléchargements 
2 . Utilisation 
d.  Bouton de fermeture et de réduction personnalisés 
1 . Transitions Dot Net 
2 . Les évènements de la souris 
3 . Résultat 
 
VII . Optionnel  - l'organisation 
a . Les régions 
b . Les commentaires 
VIII . Finitions de la Control Box 
a . Fermeture et réduction 
b . Animations 
IX . Les graphismes (deuxième partie ) 
a . Le titre et le logo de la fenêtre 
b . Optionnel  - le label personnalisé 
c . Des contours 
d . Déplacement de la fenêtre 
X . L'authentification 
a . Préparation 
1 . Les zones de texte 
2 . Le bouton de connexion 
b . Utilisation de MojangAPI 
c . AuthManager et threads
 
 
 
I. Introduction 
 
Il existe déjà plusieurs tutoriels disponibles sur Internet, et même sur le forum. 
Cependant, au vu des tutoriels proposés, je tenais à partager mon expérience de développement, et donc, ma manière de faire. 
Je vais donc tenter de vous apprendre à créer un lanceur (entendez « Lanceur ») pour Minecraft, compatible avec les dernières versions de ce dernier. 
 
 
 
 
 
II. Les bases 
 
a. Mise au point avant de démarrer  
 
J’estime ici que vous savez déjà ce qu’est un langage de programmation. Si non, je vous invite à jeter un œil sur l’article dédié de Wikipédia . Cependant, si vous ne savez même pas ce qu'est un langage de programmation, vous aurez probablement du mal à suivre ce tutoriel dans son intégralité. 
 
Pour ceux qui n’ont jamais développé ou qui ne connaissent pas Visual Basic .NET , C# .NET , ou plus globalement Visual Studio , je vous invite à lire les premiers chapitres du tutoriel VB .NET sur OpenClassrooms , histoire que vous ne soyez pas trop vite dépassés. 
Vous pouvez aussi lire le tutoriel en entier, cela ne peut pas vous faire de mal. 
 
Je vais cependant vous aider dans l’installation des outils nécessaires, car le tutoriel d’OpenClassrooms commence à se faire un petit peu vieux. :3 
 
 
b. Les outils nécessaires  
 
Pour commencer le développement de notre lanceur, nous avons besoin d’un IDE . En l’occurrence, nous aurons besoin de Visual Studio Express , la version gratuite de l’environnement de développement de Microsoft. 
 
Je vous invite à le télécharger sur le site dédié : https://www.visualstudio.com/fr-fr/downloads/download-visual-studio-vs.aspx  
 
ÉDITION  - Dracoctix a mentionné, dans les commentaires, une version plus complète de Visual Studio. Elle est gratuite et plus fonctionnelle, vous pouvez la télécharger et l'utiliser à la place de Visual Studio Express. Cliquez ici . 
 
 
Figure 1 - Téléchargement de Visual Studio Express 2015 pour Windows Desktop 
 
Descendez plus bas sur la page, sous la section « Téléchargements Visual Studio  », puis cliquez sur « Visual Studio 2015  » dans le menu latéral, et enfin, sur « Express 2015 pour Desktop  ». 
 
Sélectionnez votre langue, puis cliquez sur le bouton de téléchargement. 
Suivez les étapes, téléchargez l’exécutable, installez Visual Studio, puis ouvrez-le. 
 
 
 
 
 
III. Création du projet  
 
a. Réglages du projet 
  
J’ai créé un projet WinForms nommé Lanceur Minecraft . 
 
À noter ›  Si vous ne savez pas comment créer un projet, je vous invite à lire le tutoriel référencé dans l'introduction. Prenez garde à créer un projet WinForms et non WPF, ce n'est pas la même chose :) 
 
Je vous invite à ouvrir les propriétés du projet en double-cliquant sur My Project  dans l’explorateur de solutions. 
 
Modifiez le contenu de la zone de texte sous Espace de noms racine , de manière à ce que le contenu soit aussi court et clair que possible. 
Dans mon cas, c’était « Lanceur_Minecraft  » et je l’ai modifié en « Launcher  ». 
 
J’ai appelé mon projet « Lanceur Minecraft  » car je n'ai pas de vrai nom pour celui-ci. 
Cependant, si votre lanceur a un nom, vous pouvez l’utiliser pour l’espace de noms racine. 
En guise d'exemple, j’ai dû créer un lanceur qui devait s’appeler « Mineteam  ». J’ai donc utilisé le nom « Mineteam  » pour l’espace de noms racine. 
 
Attention ›  Gardez en tête que tous vos noms de variables et de classes devraient être en anglais. Il est très peu recommandé de les écrire en français, malgré le mauvais exemple du tutoriel d’OpenClassrooms. 
 
Choisissez ensuite la version du Framework sur laquelle vous comptez développer. Dans mon cas, je vais développer sous la 4.5. 
Cette dernière est native sur Windows à partir de Windows 8 ; mais prenez en compte que les utilisateurs de votre lanceur doivent impérativement avoir au minimum la version que vous choisirez pour pouvoir ouvrir le lanceur. Si vous comptez distribuer votre lanceur à des gens sous Windows Vista (vous ne devriez pas  ), vous devriez choisir une version inférieure. 
 
Cochez maintenant la case Application à instance unique , et choisissez À la fermeture du dernier formulaire  comme mode d’arrêt. 
 
Enfin, cliquez sur Informations de l’assembly . Une boîte de dialogue apparaît : vous pouvez la remplir avec les informations que vous souhaitez. 
 
 
Figure 2 - Informations de l'assembly de mon lanceur 
 
Validez en cliquant sur OK , puis sauvegardez le projet (Ctrl+S ). 
 
 
b. Derniers réglages 
  
Il est toujours bien de renommer ses contrôles et formulaires afin d’avoir une meilleure organisation. Je vous invite donc à renommer votre formulaire Form1  en Main . 
Pour le renommer, cliquez sur Form1.vb  dans l’Explorateur de solutions  et appuyez sur F2 . 
 
Si une boîte de dialogue s’affiche, cliquez sur Oui  : elle va renommer toutes les références à votre fenêtre comme nous le voulons. 
Si elle ne s’affiche pas, c’est que vous avez déjà changé le nom de votre formulaire dans ses propriétés. 
 
À noter ›  En anglais, « Main » veut dire « principal ». C’est une habitude et une convention chez les développeurs que les classes principales se nomment Main. 
 
Je vous invite maintenant à vous rendre dans les propriétés de votre Main . 
Voici les propriétés que nous allons changer maintenant, dans l’ordre (par catégories) : 
 
FormBorderStyle  à FixedSingle  – cela va empêcher notre utilisateur de modifier la taille de la fenêtre. 
 
 
Text  à Lanceur Minecraft  – ou ce que vous voulez : c’est le titre qui va s’afficher en tant que titre du formulaire. Je vous invite cependant à mettre quelque chose de sobre et clair, il est toujours désagréable de lire « Minecraft Launcher v3.2.08 by Xxx_MrAlbertoDu64_xxX  » en nom de fenêtre. J’exagère un peu, mais en lisant ma signature vous verrez que je n’ai aucune pitié pour les kikoos.  
 
 
Size  à 1000 ; 600  – ce sera la taille de la fenêtre. Vous pouvez mettre ce que vous souhaitez, je serai moi-même peut-être amené à la modifier par la suite. 
 
 
StartPosition  à CenterScreen  – ça va être la position de départ de la fenêtre sur notre écran. 
 
 
MiximizeBox  à False  – cela désactive le bouton Agrandir  de la fenêtre. 
 
 
MinimizeBox  à False  – pareil, avec le bouton Réduire . 
  
Nous serons peut-être à nouveau amenés à modifier ces propriétés, mais, pour le moment, nous avons modifié les bases. 
 
   
Figure 3 - État du projet après les modifications 
 
 
 
 
 
 
IV. Optionnel  - déboguer plus facilement  
 
 
a. Préparation de la classe 
  
Ceux qui ont déjà programmé le savent, déboguer un programme (trouver les erreurs dans le code qui causent un disfonctionnement, autrement dit, les bugs) peut s’avérer quelquefois plutôt difficile. 
 
Dans l’optique d’anticiper d’éventuels problèmes, nous allons écrire une classe partagée (qui n’aura donc pas besoin d’être instanciée) qui nous permettra de loguer des informations au fur et à mesure que le programme se déroule. 
 
Créez donc un nouveau dossier en effectuant un clic droit sur le nom de votre projet dans l’Explorateur de solutions , puis en sélectionnant Ajouter  > Nouveau dossier . Nommez-le « Core  ». 
 
Une fois cela fait, créez une classe à l’intérieur de ce dossier que vous nommerez « Logger  ». 
 
   
Figure 4 - Contenu de la classe automatiquement créée
 
Nous allons donc créer plusieurs fonctions que je ne vais pas expliquer, qui vont permettre d’écrire quelque chose dans un fichier sous la forme [Heure] [Niveau d’alerte] <message> . 
 
Vous pouvez copier-coller le code ci-dessous dans votre classe, je vais juste expliquer quelques petites choses. 
 
						
							 
						
						
							 
	Code (vbnet):
	Imports  System
. Text 
Public  Class  Logger
    
Private  Shared  _LogWriter 
As  IO
. StreamWriter 
    Private  Shared  _LogFile 
As  String 
    Private  Shared  _DefaultColor 
As  ConsoleColor 
=  ConsoleColor
. White 
    Public  Enum  Levels
        Normal 
=  1 
        Debug 
=  2 
        [ Warning
]  =  3 
        [ Error ]  =  4 
    End  Enum 
    ' ------------------------------------------------------------------------------- 
    ' -------- [ PUBLIC ] ----------------------------------------------------------- 
    ' ------------------------------------------------------------------------------- 
    ''' <summary> 
    ''' Writes a new line 
    ''' </summary> 
    < DebuggerHidden
( ) > 
    Public  Shared  Sub  NewLine
( ) 
        Console
. WriteLine ( ) 
    End  Sub 
    ''' <summary> 
    ''' Writes a normal text in the console, in green. 
    ''' </summary> 
    ''' <param name="Text">The text.</param> 
    < DebuggerHidden
( ) > 
    Public  Shared  Sub  Normal
( ByVal  Text 
As  String ) 
        Logger
. WriteLine ( Levels
. Normal , Text
) 
    End  Sub 
    ''' <summary> 
    ''' Writes a debug text in the console, in gray. 
    ''' </summary> 
    ''' <param name="Text">The text.</param> 
    Public  Shared  Sub  Debug
( ByVal  Text 
As  String ) 
        Logger
. WriteLine ( Levels
. Debug , Text
) 
    End  Sub 
    ''' <summary> 
    ''' Writes a warning text in the console, in yellow. 
    ''' </summary> 
    ''' <param name="Text">The text.</param> 
    < DebuggerHidden
( ) > 
    Public  Shared  Sub  Warning
( ByVal  Text 
As  String ) 
        Logger
. WriteLine ( Levels
. Warning , Text
) 
    End  Sub 
    ''' <summary> 
    ''' Writes an error text in the console, in dark red. 
    ''' </summary> 
    ''' <param name="Text">The text.</param> 
    < DebuggerHidden
( ) > 
    Public  Shared  Sub  [ Error ] ( ByVal  Text 
As  String ) 
        Logger
. WriteLine ( Levels
. Error , Text
) 
    End  Sub 
    ''' <summary> 
    ''' Writes an exception text in the console, in dark red. 
    ''' </summary> 
    ''' <param name="Exception">The exception to log.</param> 
    < DebuggerHidden
( ) > 
    Public  Shared  Sub  Exception
( ByVal  Exception 
As  Exception
) 
        Logger
. NewLine ( ) 
        Logger
. Error ( Logger
. GetSeparator ( Levels
. Error ) ) 
        Logger
. Error ( Exception
. Message ) 
        Logger
. Error ( Exception
. StackTrace ) 
        Logger
. Error ( Exception
. StackTrace ) 
        Logger
. Error ( Logger
. GetSeparator ( Levels
. Error ) ) 
        Logger
. NewLine ( ) 
    End  Sub 
    ' ------------------------------------------------------------------------------- 
    ' -------- [ PRIVATE ] ---------------------------------------------------------- 
    ' ------------------------------------------------------------------------------- 
    Private  Shared  Function  GetSeparator
( Optional  ByVal  Level 
As  Levels 
=  Levels
. Normal ) 
        Dim  Header 
As  String  =  "" 
        For  i 
=  Header
. Length  To  Console
. WindowWidth  -  Level
. ToString . Length  -  Date . Now . ToString ( "HH:mm:ss" ) . Length  -  8 
            Header 
&=  "-" 
        Next 
        Return  Header
    
End  Function 
    ''' <summary> 
    ''' Writes a line in the logger with the specified color. 
    ''' </summary> 
    ''' <param name="Level">The line's level.</param> 
    ''' <param name="Text">The text.</param> 
    Private  Shared  Sub  WriteLine
( ByVal  Level 
As  Levels, 
ByVal  Text 
As  String ) 
        Dim  Timestamp 
As  String  =  Date . Now . ToString ( "HH:mm:ss" ) 
        ' If Not (Level = Levels.Debug And LauncherVariables.DEBUG = False) Then Console.WriteLine("[{0}] [{1}] {2}", Timestamp, Level.ToString, Text) 
        Logger
. WriteInFile ( String . Format ( "[{0}] [{1}] {2}" , Timestamp, Level
. ToString , Text
) ) 
    End  Sub 
    ''' <summary> 
    ''' Logs the logs in a file. 
    ''' </summary> 
    Private  Shared  Sub  WriteInFile
( ByVal  Text 
As  String ) 
        If  IsNothing
( Logger
. _LogWriter
)  Then 
            If  Not  IO
. Directory . Exists ( "logs/" )  Then  IO
. Directory . CreateDirectory ( "logs/" ) 
            Logger
. _LogFile 
=  "logs/"  &  Date . Now . ToString ( "MM-dd-yyyy-HH-mm" )  &  "-logs.txt" 
            Logger
. _LogWriter 
=  New  IO
. StreamWriter ( Logger
. _LogFile, 
True , Encoding
. UTF8 ) 
        End  If 
        Try 
            Logger
. _LogWriter
. WriteLine ( Text
) 
            Logger
. _LogWriter
. Flush ( ) 
        Catch  ex 
As  Exception
            
MsgBox ( ex
. ToString ) 
        End  Try 
    End  Sub 
    ' ------------------------------------------------------------------------------- 
    ' -------- [ LOGGER ] ----------------------------------------------------------- 
    ' ------------------------------------------------------------------------------- 
    ''' <summary> 
    ''' Finalizes the logger and close it properly. 
    ''' </summary> 
    < DebuggerHidden
( ) > 
    Public  Shared  Shadows  Sub  Finalize
( ) 
        Logger
. _LogWriter
. Close ( ) 
        Logger
. _LogWriter
. Dispose ( ) 
    End  Sub 
End  Class  
   
						 
					  
 
La ligne Public Enum  Levels  ainsi que le contenu de son bloc sont une énumération  : cela permet de récupérer des valeurs à l’aide d’un nom. C’est un peu comme des variables, sauf que les valeurs ne changent pas et les noms sont regroupés sous un autre nom. 
 
À noter ›  Certains noms sont entre crochets. Ce sont des mots clés réservés à notre IDE pour pouvoir identifier certains types, variables globales, etc… les mettre entre crochet permet de malgré tout utiliser le nom voulu. 
 
Ici, on peut accéder à la valeur de Debug  en écrivant Logger .Levels .Debug . Cela permet généralement la facilitation des conditions. 
 
Dans notre cas, nous n’en avons pas vraiment besoin puisque j’ai choisi de créer une fonction pour chaque niveau d’alerte. Nous pourrons donc écrire du debug en appelant Logger .Debug ("Test" ), au lieu de Logger .WriteLine(Levels .Debug, "Test"  ). 
 
Attention ›  J’ai mis la fonction WriteLine en Private, cela change son niveau d’accès : vous n’aurez pas accès à la fonction en dehors de la classe. C’est un concept de Programmation Orientée Objet (POO), vous pouvez en apprendre plus sur le tutoriel que je vous ai donné au début du tutoriel. 
 
   
Figure 5 - Contenu de la classe Logger
 
Attention ›  Si vous êtes attentifs, vous avez remarqué qu’une classe LauncherVariables  a été créée. Je vous expliquerai ce qu’il en est plus tard. 
 
 
b. Premier débogage  
 
Je vous invite à vous rendre sur votre Main  et à double-cliquer sur la fenêtre. 
Cela va vous créer un Évènement  dans le fichier correspondant à la classe Main . 
 
Écrivez « Logger.Debug("Test")  » dans cet évènement, puis lancez le programme avec la touche F5 . 
 
   
Figure 6 - Première ligne dans notre premier évènement 
 
Sous vos yeux ébahis (ou peut-être pas), une fenêtre blanche s’affiche. Vous pouvez fermer le programme. 
 
Pour les plus à l’ouest d’entre vous, vous vous demandez pourquoi je vous ai fait ouvrir la fenêtre, et/ou pourquoi ne s’est-il rien passé alors que nous avons écrit une ligne de code. 
 
Pour ceux qui suivent et qui ont analysé le code de la classe Logger , vous avez déjà ouvert le répertoire de votre solution à la recherche du fichier log. 
Comment ça non ?  
 
Effectuez un clic droit sur le nom de votre projet dans l’Explorateur de solutions  et cliquez sur Ouvrir  dans l’Explorateur de fichiers . Rendez-vous dans bin  > Debug  > logs . Là, étincelant, votre tout premier log. Vous pouvez l’ouvrir. 
 
   
Figure 7 - Tout premier log 
 
 
Si vous avez suivi, vous savez qu’à chaque action un peu importante dans votre programme, vous appellerez la fonction Debug  de votre Logger  afin d’écrire dans ce fichier des informations de debug. 
 
 
 
 
 
V. La classe LauncherVariables 
 
Nous allons vite passer dessus, c’est simplement une classe partagée (comme la classe Logger ) qui va contenir des variables globales au lanceur. 
 
Par exemple, la mienne contient la ligne Public Const  DEBUG  As Boolean  =  True  qui permet de savoir si l’on veut déboguer ou non. 
 
Je vous invite donc à créer cette classe et à y mettre cette ligne. 
 
   
Figure 8 - La classe LauncherVariables 
 
Attention ›  Cette classe et son contenu seront amenés à changer avec le futur système de paramètres. 
 
 
 
 
 
VI. Les graphismes 
 
Histoire de ne pas trop vous faire languir, nous allons passer à l’aspect graphique du lanceur . 
Cependant, malgré les graphismes que je vais adopter, vous pouvez très bien créer les vôtres, et totalement innover. Je ne suis pas excellent en graphismes, je vais donc faire le minimum nécessaire . 
 
Vous avez sans doute déjà vu pas mal de lanceurs, certains jolis, certains moches. Pratiquement aucun n’adopte une charte graphique, et tous - ou presque - ont vu leur design créés à coup de « tiens c’est pas mal, je vais laisser ça comme ça  ». 
 
Eh bien, contre toute attente... je vais faire pareil. :3 
Je ne vais pas me plier aux règles d’une charte graphique comme le Flat UI  ou le Material UI de Google  car ce serait trop long, mais sachez que vous, qui lisez ce tutoriel, et qui créez un lanceur pour votre serveur, devriez respecter une de ces chartes pour que votre lanceur soit uniforme et agréable à l’œil. 
Cependant, vous pouvez aussi me recopier. Vous avez le droit.  
 
 
a. Les choses à éviter  
Les textes en gras  
Quelque chose d’extrêmement désagréable à voir sur un formulaire quelconque, que ce soit un lanceur Minecraft ou autre, est un texte en gras mal géré. Si vous comptez mettre quelque chose en évidence, utilisez des polices comme Roboto Medium , mais ne mettez pas du gras, car les polices rendent souvent très mal sur un formulaire. 
 
Les couleurs flashy  
Vous vous en doutez certainement, mais mettre du vert fluo en image de fond sur votre lanceur n’est pas une bonne idée. 
 
Les fautes d’orthographe  
Une faute de frappe c’est vite arrivé, mais si vous n’êtes pas capables d’aligner 10 mots sans faire une faute d’orthographe, utilisez un p*tain de  correcteur orthographique. Rien de plus désagréable que de lire un texte rempli de fautes, et je ne suis pas le seul de cet avis. De plus, un rendu sans faute rendra votre lanceur plus professionnel. 
 
Les mauvais alignements  
Quand vous alignez des contrôles (que nous verrons plus tard) tels que des étiquettes (labels ), boutons, ou autres éléments graphiques, veillez à ce qu’ils soient alignés (vous pouvez vous aider des valeurs numériques des propriétés Size  et Location , de la propriété Dock , et de la barre d'outils Disposition ) 
 
Évitez les ombres et le biseautage  
Hormis sur les cadres (panels ), les ombres sont à proscrire. De même, le biseautage dans un nom de serveur écrit à la va-vite sur une version tout à fait légale de  Photoshop. 
 b. L’image de fond  
 
J’ai l’intention d’utiliser, pour mes graphismes, une image de fond. Mais sachez qu’une image de fond possède un gros désavantage : elle rendra votre lanceur plus lourd . 
Que ce soit au téléchargement ou à l’exécution, une image rendra plus lourd votre lanceur. Si vous n’avez pas un ordinateur très puissant (comme moi), vous pourriez voir des défauts d’affiche lors de l’affichage , de la fermeture  ou du déplacement  de votre fenêtre. 
Pour éviter cela un maximum, prenez une image compressée  (pas trop quand même) et qui fait la taille exacte de votre lanceur : ni trop grande, ni trop petite. 
 
Voici l’image de fond que j’ai choisie : 
 
   
Vous pouvez la télécharger en effectuant un clic droit, puis "Enregistrer sous" 
 
C’est une image que j’ai trouvée sur Google. Je l’ai réduite à une taille de 1000 * 600 pixels  et floutée à 15% . 
Vous êtes évidemment libre de choisir votre propre image, comme par exemple, une capture d’écran de votre serveur (un endroit intéressant, pas l’herbe, hm ?). Je vous conseille également le flou . 
 
Rendez-vous donc dans les propriétés de votre Main  et cliquez sur BackgroundImage . Sélectionnez le bouton radio du bas, et cliquez sur Importer . Choisissez votre image, puis validez. 
Enfin, mettez la valeur Zoom  à BackgroundImageLayout , cela aura pour effet de cadrer l’image dans votre fenêtre (notez que vous n’avez pas besoin de faire ça si vous avez suivi mes conseils). 
Si ça ne va pas avec votre image, essayez Stretch   (« étirer  »), ou si vous avez choisi un modèle (pattern ) tel que l’image d’un cube de terre, choisissez Tile  (« tuile  », soit « répétition  »). 
 
Pour un meilleur rendu, j’ai choisi de finalement retirer les bordures de la fenêtre. Pour cela, mettez la valeur « None  » à FormBorderStyle , et n’oubliez pas de remettre la taille de la fenêtre à  1000 * 600 , car elle a été modifiée. 
 
Enfin, mettez un Panel  (qui se trouve dans la boite à outils, si vous ne la trouvez pas, ouvrez-la en appuyant sur Ctrl+W, puis X , ou en allant dans Affichage  > Boîte à outils ) dans votre formulaire. 
 
Accédez aux propriétés du Panel  et changez ces valeurs : 
Name  à PNL_TOP  – Il est toujours aussi important de modifier les noms des contrôles. 
 
Dock  à Top  – Ainsi, le Panel sera lié au haut de notre fenêtre. 
 
Size  à 1000 ; 38  – De toute façon, vous ne pouvez pas modifier le 1000. Le 38 correspond à la hauteur du Panel . 
BackColor  à 153 ; 0 ; 0 ; 0  – Cela correspond à un fond noir avec une opacité de 60%  (60 / 100 * 255). 
  
 
c. Les polices d’écriture personnalisées  
 
1. Téléchargements  
 
Afin de parvenir à une meilleure personnalisation, vous allez être amenés à utiliser vos propres polices. 
Je vous conseille donc de télécharger celles-ci : 
Material Icons  - c'est une police d'écriture créée et fournie par Google qui contient un symbole à chaque caractère. Elle est extrêmement utile (et jolie), je vais beaucoup l'utiliser dans ce projet. 
Roboto  - c'est aussi une police d'écriture de Google, et elle rend elle aussi très bien. Je vous la conseille également. 
 À noter ›  Pour télécharger Roboto, cliquez sur la flèche en haut à droite du compteur, et cliquez sur Zip File. 
 
 
Figure 9 - téléchargement de la police Roboto 
 
 
2. Utilisation  
 
Afin de les utiliser, vous allez devoir commencer par les importer dans votre projet . 
Pour cela, allez dans les propriétés du projet (My Project ) et cliquez sur l’onglet Ressources . Faites un glisser-déposer des polices précédemment téléchargées dans la zone blanche. 
 
     
Figure 10 - Importation de la police d'écriture Material Icons Regular 
 
Cela fait, créez une classe dans le dossier Core , que vous nommerez FontManager . 
 
Collez-y ce code, que vous n’avez pas besoin de comprendre. Sachez juste qu’il permet de récupérer un objet de type Font  grâce à un tableau de Byte . 
 
						
							 
						
						
							 
	Code (vbnet):
	Imports  System. Drawing . Text  
Imports  System. Runtime . InteropServices  
 
Public  Class  FontManager 
 
    Private  Shared  _FontCollection As  PrivateFontCollection 
 
    ''' <summary>  
    ''' Get an instance of a given font.  
    ''' </summary>  
    ''' <param name="Font">The font to use, for example, in the resources.</param>  
    ''' <param name="Size">The size of the font, in pixels. 12 by default.</param>  
    ''' <param name="Style">The style of the font, regular by default.</param>  
    Public  Shared  Function  GetFont( ByRef  Font( )  As  Byte , Optional  ByVal  Size As  Single  =  12 , Optional  ByVal  Style As  FontStyle =  FontStyle. Regular )  As  Font 
        If  FontManager. _FontCollection Is  Nothing  Then  LoadFont( Font)  
        Return  New  Font( FontManager. _FontCollection. Families ( 0 ) , Size, Style)  
 
    End  Function  
 
    ''' <summary>  
    ''' Load a font in the FontCollection  
    ''' </summary>  
    Private  Shared  Sub  LoadFont( ByRef  Font( )  As  Byte )  
        Try  
            FontManager. _FontCollection =  New  PrivateFontCollection ' On initialise la collection  
            Dim  FontPointer As  IntPtr =  Marshal. AllocCoTaskMem ( Font. Length )  ' On crée un pointeur vers une partie de la mémoire  
 
            Marshal. Copy ( Font, 0 , FontPointer, Font. Length )  ' On copie la police dans la mémoire  
            FontManager. _FontCollection. AddMemoryFont ( FontPointer, Font. Length )  ' On ajoute la police se trouvant dans la mémoire dans la collection  
            Marshal. FreeCoTaskMem ( FontPointer)  ' On libère la mémoire précédemment utilisée  
 
        Catch  ex As  Exception 
            Logger. Exception ( ex)  ' Nous loggons notre exception  
        End  Try  
    End  Sub  
 
End  Class 
   
						 
					  
 
À noter ›  Si vous souhaitez malgré tout comprendre le code, il est en partie commenté. 
 
Créez maintenant une étiquette (Label ) que vous placerez dans le PNL_TOP . Changez les propriétés suivantes : 
 
BackColor  à Transparent  (ou 0 ;0 ;0 ;0 ) – de manière à rendre son fond transparent 
Cursor  à Hand  – afin que notre souris se transforme en main 
ForeColor  à #ecf0f1   – une nuance du blanc 
TextAlign  à MiddleCenter  
Name  à LBL_CLOSE  – afin de l’identifier dans le code 
Dock  à Right – c’est important, cela sert à coller l’étiquette à droite du Panel. 
Size  à 38 ; 38 – pour que cela forme un carré de côté 38 px. 
  
Votre bouton Fermer  est presque prêt. Rendez-vous dans l’éditeur de code, et dans l’évènement Main . S’il y a toujours la ligne de debug, vous pouvez l’enlever. Ajoutez-y ces lignes : 
 
	Code (vbnet):
	Me . LBL_CLOSE . Font  =  FontManager
. GetFont ( My
. Resources . MaterialIcons_Regular , 
15 ) 
Me . LBL_CLOSE . Text  =  ChrW ( & HE5CD
)  
 La première permet de charger la police grâce au FontManager . Le 15  est la taille de la police . La seconde permet d’écrire le caractère unicode correspondant à la croix  dans la tableau des caractères de la police (donc E5CD ). 
 
À noter ›   Le préfixe &H  permet de rentrer un nombre de base 16, c’est-à-dire un nombre hexadécimal . En C#, on pourrait directement écrire « \ue5cd  » dans une chaîne de caractère ; en VB, on utilise la fonction ChrW  pour récupérer ce caractère. 
 
À noter ›  Vous pouvez vous rendre sur la page GitHub de la police d’écriture  pour avoir plus de logos. Vous pouvez également installer la police sur votre PC et ouvrir charmap.exe (Windows+R , charmap , puis touche Entrée ) pour les voir. Le code correspondant est affiché en bas.
 
   
Figure 11 - La fenêtre Exécuter et la fenêtre Charmap 
 
Vous pouvez maintenant ouvrir le programme avec F5 . Surprise ! Une jolie croix apparaît en haut à droite. Mais elle n’est pas encore fonctionnelle . 
 
 
d. Bouton de fermeture et de réduction personnalisés  
 
1. Transitions Dot Net  
Nous allons devoir utiliser ce qu’on appelle une bibliothèque . Sortez donc de chez vous, rendez-vous dans la bibliothèque la plus proche et kidnappez la bibliothécaire.  
 
Une bibliothèque est en fait une liste de fonctions déjà écrites par quelqu’un d’autre, qui nous mâche bien le travail, parce qu’on est des flemmards. 
 
Téléchargez donc la bibliothèque « Transition Dot Net  » à cette adresse , et extrayez-la vers un dossier sur votre disque dur. 
 
Rendez-vous dans les propriétés de votre projet, onglet Références , cliquez sur Ajouter , Parcourir , trouvez le fichier Transitions.dll  là où vous l’avez extrait, puis validez en cliquant sur OK . 
 
Félicitations, vous venez d’importer votre première bibliothèque  ! :) 
 
Cette dernière va en fait nous servir à effectuer des transitions (oui c’est moi, Captain Obvious ) afin de rendre notre bouton plus joli. 
 
 
2. Les évènements de la souris  
 
Je vous invite maintenant à cliquer sur l’icône en forme d’éclair  en haut des propriétés de l’étiquette et à double-cliquer sur la zone de texte à droite de MouseEnter , en bas. 
 
 
Figure 12 - onglet des évènements de l'étiquette 
 
Cela nous amène dans l’éditeur de code, dans la méthode correspondant à l’évènement appelé lorsque l’on survole l’étiquette avec la souris. 
 
Mettez-y le code suivant : 
	Code (vbnet):
	 
Transition. run ( LBL_CLOSE, "ForeColor" , ColorTranslator. FromHtml ( "#e57373" ) , New  TransitionType_Linear( 250 ) )  
Transition. run ( LBL_CLOSE, "BackColor" , Color. FromArgb ( 100 , 0 , 0 , 0 ) , New  TransitionType_Linear( 250 ) )  
 
 Ouvrez maintenant l’évènement MouseLeave  et insérez-y ce code : 
	Code (vbnet):
	 
Transition. run ( LBL_CLOSE, "ForeColor" , ColorTranslator. FromHtml ( "#ecf0f1" ) , New  TransitionType_Linear( 250 ) )  
Transition. run ( LBL_CLOSE, "BackColor" , Color. FromArgb ( 0 , 0 , 0 , 0 ) , New  TransitionType_Linear( 250 ) )  
 
 Attention ›  N'oubliez pas d'importer Transitions  dans votre classe. Sans l'import, il va y avoir des erreurs : placez Imports Transitions  en début de fichier. 
 
Analysons ces lignes. 
La première permet d’effectuer une transition linéaire d’une durée de 250 millisecondes  de la valeur actuelle de la propriété ForeColor  à une nouvelle valeur, soit la couleur « #e57373   » qui correspond à une nuance de rouge des codes couleurs de Google . 
 
À noter ›  Je vais souvent réutiliser ces codes, vous devriez vous aussi garder cette page à portée de main, et même, en favoris. 
 
La seconde permet d’effectuer la même transition, mais de la couleur de fond, et change simplement l’opacité en l’augmentant à 39% . 
 
Les lignes de l’évènement MouseLeave  font la même chose en sens inverse. 
 
Ouvrez maintenant votre lanceur avec F5 , et passez votre souris sur votre bouton de fermeture. N’est-ce pas magnifique ? 
 
Je vous laisse maintenant copier ce bouton pour créer un bouton de réduction. Pour cela, vous devez savoir : 
Le nom du bouton : LBL_REDUCE  
Couleur du fondu : #4fc3f7  
Valeur unicode du bouton : e5cf  ou e15b  
  
Les évènements sont donc les mêmes que pour l’étiquette de fermeture avec certaines valeurs changées. Je vous laisse vous débrouiller. :3 
 
 
3. Résultats  
 
C’est bon ? Vous avez finit ? Allez, je vous file le code. 
 
	Code (vbnet):
	
Imports  Transitions
Public  Class  Main
  
Private  Sub  Main_Load
( sender 
As  Object , e 
As  EventArgs
)  Handles  MyBase . Load 
  Me . PNL_TOP . Font  =  FontManager
. GetFont ( My
. Resources . MaterialIcons_Regular , 
15 ) 
  Me . LBL_CLOSE . Font  =  PNL_TOP
. Font 
  Me . LBL_CLOSE . Text  =  ChrW ( & HE5CD
) 
  Me . LBL_REDUCE . Font  =  PNL_TOP
. Font 
  Me . LBL_REDUCE . Text  =  ChrW ( & HE5CF
) 
  End  Sub 
  Private  Sub  LBL_CLOSE_MouseEnter
( sender 
As  Object , e 
As  EventArgs
)  Handles  LBL_CLOSE
. MouseEnter 
  Transition
. run ( LBL_CLOSE, 
"ForeColor" , ColorTranslator
. FromHtml ( "#e57373" ) , 
New  TransitionType_Linear
( 250 ) ) 
  Transition
. run ( LBL_CLOSE, 
"BackColor" , Color
. FromArgb ( 100 , 
0 , 
0 , 
0 ) , 
New  TransitionType_Linear
( 250 ) ) 
  End  Sub 
  Private  Sub  LBL_CLOSE_MouseLeave
( sender 
As  Object , e 
As  EventArgs
)  Handles  LBL_CLOSE
. MouseLeave 
  Transition
. run ( LBL_CLOSE, 
"ForeColor" , ColorTranslator
. FromHtml ( "#ecf0f1" ) , 
New  TransitionType_Linear
( 250 ) ) 
  Transition
. run ( LBL_CLOSE, 
"BackColor" , Color
. FromArgb ( 0 , 
0 , 
0 , 
0 ) , 
New  TransitionType_Linear
( 250 ) ) 
  End  Sub 
  Private  Sub  LBL_REDUCE_MouseEnter
( sender 
As  Object , e 
As  EventArgs
)  Handles  LBL_REDUCE
. MouseEnter 
  Transition
. run ( LBL_REDUCE, 
"ForeColor" , ColorTranslator
. FromHtml ( "#4fc3f7" ) , 
New  TransitionType_Linear
( 250 ) ) 
  Transition
. run ( LBL_REDUCE, 
"BackColor" , Color
. FromArgb ( 100 , 
0 , 
0 , 
0 ) , 
New  TransitionType_Linear
( 250 ) ) 
  End  Sub 
  Private  Sub  LBL_REDUCE_MouseLeave
( sender 
As  Object , e 
As  EventArgs
)  Handles  LBL_REDUCE
. MouseLeave 
  Transition
. run ( LBL_REDUCE, 
"ForeColor" , ColorTranslator
. FromHtml ( "#ecf0f1" ) , 
New  TransitionType_Linear
( 250 ) ) 
  Transition
. run ( LBL_REDUCE, 
"BackColor" , Color
. FromArgb ( 0 , 
0 , 
0 , 
0 ) , 
New  TransitionType_Linear
( 250 ) ) 
  End  Sub 
End  Class 
  
 Je ne sais pas vous, mais je trouve ce code assez désorganisé. Nous voulons écrire un code propre, donc nous allons voir comment nous organiser parmi les classes et les méthodes. 
 
 
 
 
 
 
VII. Optionnel  - l'organisation  
 
Plus tôt dans ce tutoriel, je vous ai demandé de créer un dossier nommé « Core  » dans l’arborescence des fichiers du projet. 
 
Cela permet, au fur et à mesure que le nombre de fichiers dans le projet grandit, de rester organiser. En effet, plus le code va grandir, plus vous ajouterez de fichiers, de classes, etc. D’où le principe de les regrouper par catégorie. 
 
Ici, le dossier Core  contient tout ce qui est lié au fonctionnement interne du lanceur. Core  veut dire « noyau  », je ne sais pas si c’est la meilleure manière de nommer le dossier, mais elle reste assez parlante. 
 
Par exemple, si le nombre de classe servant à gérer certains aspects du lanceur (managers ), comme le FontManager , voient le jour dans ce projet, je vais certainement toutes les mettre dans un dossier Managers . 
 
De même que nous trions l’arborescence d’un projet, les lignes de code à l’intérieur des fichiers de ce dernier doivent elle aussi être organisées. 
 
 
a. Les régions 
  
Le charabia que j’ai écrit plus haut étant un bel exemple de ce qu’il ne faut pas faire , je vous conseille donc de ranger ces lignes de code par catégories grâce au mot-clé #Region   (avec le # ). 
 
Par exemple : 
	Code (vbnet):
	#Region ’’Events’’
    Private  Sub  Main_Load
( )  …
    #Region “ControlBox”
        
Private  Sub  LBL_CLOSE_MouseEnter
( )  …
        
Private  Sub  LBL_CLOSE_MouseLeave 
( )  …
    
#End  Region
#End  Region
 
 
 C’est ainsi que nous allons nous organiser. 
 
 
b. Les commentaires  
 
Il faut aussi veiller à commenter certaines fonctions. 
Que ce soit par esthétique du code ou par prévention de relecture, il faut s’habituer à commenter nos lignes de code. Particulièrement les fonctions : mettez trois apostrophes sur la ligne au-dessus d’une méthode  et vous pourrez écrire à quoi elle sert. 
Ce sera notamment utile lors du survol à la souris d’un appel à sa fonction pour voir ce que vous avez écrit, donc son fonctionnement , et à l’écriture de ses arguments pour voir le type et le but de ces arguments . 
 
 
Figure 13 - Le commentaire prend trois lignes et est entre balises 
 
Je vous invite donc à copier-coller le code ci-dessous (ou à le réorganiser vous-même) afin d’organiser notre charabia. 
 
	Code (vbnet):
	Imports  Transitions
Imports  Launcher
. LauncherMethods 
Public  Class  Main
#Region 
" Évenements " 
  ' ------------------------------------------------------------------------------------- 
  ' ----- [ FORMULAIRE ] ---------------------------------------------------------------- 
  ' ------------------------------------------------------------------------------------- 
  ''' <summary> 
  ''' Se déclenche lorsque la fenêtre s'ouvre. 
  ''' </summary> 
  Private  Sub  Main_Load
( sender 
As  Object , e 
As  EventArgs
)  Handles  MyBase . Load 
  Me . PNL_TOP . Font  =  FontManager
. GetFont ( My
. Resources . MaterialIcons_Regular , 
15 ) 
  Me . LBL_CLOSE . Font  =  PNL_TOP
. Font 
  Me . LBL_CLOSE . Text  =  ChrW ( & HE5CD
) 
  Me . LBL_REDUCE . Font  =  PNL_TOP
. Font 
  Me . LBL_REDUCE . Text  =  ChrW ( & HE5CF
) 
  End  Sub 
  ' ------------------------------------------------------------------------------------- 
  ' ----- [ CONTROL BOX ] --------------------------------------------------------------- 
  ' ------------------------------------------------------------------------------------- 
  ''' <summary> 
  ''' Se déclenche lorsque la souris entre sur le bouton de fermeture. 
  ''' </summary> 
  Private  Sub  LBL_CLOSE_MouseEnter
( sender 
As  Object , e 
As  EventArgs
)  Handles  LBL_CLOSE
. MouseEnter 
  Transition
. run ( LBL_CLOSE, 
"ForeColor" , ColorTranslator
. FromHtml ( "#e57373" ) , 
New  TransitionType_Linear
( 250 ) ) 
  Transition
. run ( LBL_CLOSE, 
"BackColor" , Color
. FromArgb ( 100 , 
0 , 
0 , 
0 ) , 
New  TransitionType_Linear
( 250 ) ) 
  End  Sub 
  Private  Sub  LBL_CLOSE_MouseLeave
( sender 
As  Object , e 
As  EventArgs
)  Handles  LBL_CLOSE
. MouseLeave 
  Transition
. run ( LBL_CLOSE, 
"ForeColor" , ColorTranslator
. FromHtml ( "#ecf0f1" ) , 
New  TransitionType_Linear
( 250 ) ) 
  Transition
. run ( LBL_CLOSE, 
"BackColor" , Color
. FromArgb ( 0 , 
0 , 
0 , 
0 ) , 
New  TransitionType_Linear
( 250 ) ) 
  End  Sub 
  ''' <summary> 
  ''' Se déclenche lorsque la souris entre sur le bouton de réduction. 
  ''' </summary> 
  Private  Sub  LBL_REDUCE_MouseEnter
( sender 
As  Object , e 
As  EventArgs
)  Handles  LBL_REDUCE
. MouseEnter 
  Transition
. run ( LBL_REDUCE, 
"ForeColor" , ColorTranslator
. FromHtml ( "#4fc3f7" ) , 
New  TransitionType_Linear
( 250 ) ) 
  Transition
. run ( LBL_REDUCE, 
"BackColor" , Color
. FromArgb ( 100 , 
0 , 
0 , 
0 ) , 
New  TransitionType_Linear
( 250 ) ) 
  End  Sub 
  Private  Sub  LBL_REDUCE_MouseLeave
( sender 
As  Object , e 
As  EventArgs
)  Handles  LBL_REDUCE
. MouseLeave 
  Transition
. run ( LBL_REDUCE, 
"ForeColor" , ColorTranslator
. FromHtml ( "#ecf0f1" ) , 
New  TransitionType_Linear
( 250 ) ) 
  Transition
. run ( LBL_REDUCE, 
"BackColor" , Color
. FromArgb ( 0 , 
0 , 
0 , 
0 ) , 
New  TransitionType_Linear
( 250 ) ) 
  End  Sub 
#End  Region
End  Class 
  
 À noter ›  Vous avez sans doute remarqué l’espèce de grand commentaire sur trois lignes. Je n’aime pas les régions imbriquées, j’ai donc choisi ce commentaire pour séparer mes évènements dans la région correspondante. 
 
 
VII. Finitions de la Control Box 
 
a. Fermeture et réduction  
 
Notre Control Box  est certes, jolie, mais pour le moment non-fonctionnelle : nous allons remédier à cela. Ouvrez l’évènement MouseClick  des deux étiquettes  en double-cliquant dessus . 
 
Dans l’évènement du bouton de fermeture , insérez ce code : Me .Close . Il permet de fermer la fenêtre. 
 
Dans l’évènement du bouton de réduction , insérez celui-ci : Me .WindowState =  FormWindowState .Minimized . Il permet de réduire notre fenêtre. 
 
 
b. Animations  
 
Tout cela est bien joli, mais justement, pas assez (oui, c’est moi qui ai dit que je ne m’attarderai pas sur les graphismes… chut.). 
 
Nous allons animer la fermeture de notre fenêtre par un joli fondu. Ouvrez l’évènement FormClosing  de votre Main. 
 
   
Figure 14 - Ouverture de l'évènement FormClosing 
 
Malheureusement, il n’est pas possible de modifier l’opacité de la fenêtre à l’aide de la bibliothèque Transtion Dot Net . Nous allons donc devoir passer par un autre moyen. 
 
Créez un dossier « Miscellaneous  » et déplacez-y la classe LauncherVariables . Créez maintenant une classe LauncherMethods . Nous allons mettre dedans cette classe des méthodes globales, utiles un peu partout. 
 
Vous pouvez y coller ce code : 
	Code (vbnet):
	
Public  Class  LauncherMethods
#Region 
" Fondu " 
    Public  Enum  FadeAction
        Show
        Hide
    
End  Enum 
    Public  Enum  FadeTime
        Slow 
=  500 
        Medium 
=  250 
        Fast 
=  185 
    End  Enum 
    ''' <summary> 
    ''' Permet d'afficher ou de cacher une fenêtre en fondu. 
    ''' </summary> 
    Public  Shared  Sub  FadeWindow
( Target 
As  Form, 
ByVal  Action 
As  FadeAction, 
Optional  ByVal  FadeTime 
As  FadeTime 
=  500 , 
Optional  ByVal  OPMAX 
As  Integer  =  100 ) 
        Try 
            Select  Case  Action
                
Case  FadeAction
. Show 
                    Target
. Opacity  =  0 
                    Target
. Show ( ) 
                    Dim  Inc 
As  Integer 
                    Dim  checkT 
As  Integer  =  My
. Computer . Clock . TickCount 
                    Do  While  Inc 
<  FadeTime
                        Inc 
=  My
. Computer . Clock . TickCount  -  checkT
                        Target
. Opacity  =  Inc 
/  FadeTime
                        
If  Target
. Opacity  >=  OPMAX 
Then  Exit  Sub 
                        Application
. DoEvents ( ) 
                    Loop 
                Case  FadeAction
. Hide 
                    If  Target
. Opacity  =  0  Then  Exit  Sub 
                    Dim  Inc 
As  Integer 
                    Dim  checkT 
As  Integer  =  My
. Computer . Clock . TickCount 
                    Do  While  Inc 
<  FadeTime
                        Inc 
=  My
. Computer . Clock . TickCount  -  checkT
                        Target
. Opacity  =  1  -  1  /  ( FadeTime 
/  Inc
) 
                        Application
. DoEvents ( ) 
                    Loop 
            End  Select 
        Catch  ex 
As  Exception
            Logger
. Exception ( ex
) 
        End  Try 
    End  Sub 
#End  Region
End  Class 
  
 Vous pouvez maintenant mettre, à l’intérieur de l’évènement FormClosing , cet appel : LauncherMethods .FadeWindow(Me , FadeAction .Hide, FadeTime .Fast) . 
 
Attention ›  N’oubliez pas d’importer LauncherMethods  en début de fichier ! 
 
Si vous démarrez votre lanceur et que vous le fermez à l’aide du bouton, il devrait disparaître en un léger fondu. 
 
À noter ›  Les clignotements  (flickers  en anglais) qui apparaissent sont dûs aux WinForms , plus particulièrement à l’image de fond . Il n’est malheureusement pas possible de les faire disparaître totalement. Vous pouvez vous renseigner sur WPF  qui est fait pour ça, mais je vais continuer ce tutoriel en WinForms . 
 
Le mieux que l’on puisse faire pour faire disparaître ces clignotements est de rajouter cette ligne dans l’évènement Load  du Main  : Me .SetStyle(ControlStyles .AllPaintingInWmPaint Or ControlStyles .UserPaint Or ControlStyles .DoubleBuffer, True ) . Mais au fur et à mesure que le lanceur s’alourdira, les clignotements peuvent revenir. 
 
Maintenant, vous pouvez ajouter ce même appel dans l’évènement Load  afin d’ouvrir le lanceur en fondu. N’oubliez pas de remplacer FadeAction .Hide  par FadeAction .Show , sinon, ce ne sera pas joli.  
 
 
 
 
 
 
IV. Les graphismes (deuxième partie) 
 
Nous allons continuer la création des graphismes du lanceur. Tout d’abord, commencez par réorganiser le code : nous avons trop de lignes dans l’évènement Load , nous allons donc créer une fonction d’initialisation . 
 
Commencez par créer une nouvelle région « Méthodes  » au-dessus de la région « Évènements  ». Cela fait, créez une partie « Formulaire  » à l’aide de commentaires, puis créez une fonction « Initialize  » avec les lignes de l’évènement Load , mais commentées . Le tout dans un bloc Try/Catch . 
 
Voici le code : 
 
	Code (vbnet):
	
#Region 
" Méthodes " 
  ' ------------------------------------------------------------------------------------- 
  ' ----- [ FORMULAIRE ] ---------------------------------------------------------------- 
  ' ------------------------------------------------------------------------------------- 
  Private  Sub  Initialize
( ) 
   Try 
      ' Prévention des scintillements 
     Me . SetStyle ( ControlStyles
. AllPaintingInWmPaint  Or  ControlStyles
. UserPaint  Or  ControlStyles
. DoubleBuffer , 
True ) 
    ' Affichage en fondu 
    LauncherMethods
. FadeWindow ( Me , FadeAction
. Show , FadeTime
. Fast ) 
    ' Modification de la control box 
    Me . PNL_TOP . Font  =  FontManager
. GetFont ( My
. Resources . MaterialIcons_Regular , 
15 ) 
    Me . LBL_CLOSE . Font  =  PNL_TOP
. Font 
    Me . LBL_CLOSE . Text  =  ChrW ( & HE5CD
) 
    Me . LBL_REDUCE . Font  =  PNL_TOP
. Font 
    Me . LBL_REDUCE . Text  =  ChrW ( & HE5CF
) 
  Catch  ex 
As  Exception
    Logger
. Exception ( ex
) 
  End  Try 
End  Sub 
#End  Region
 
 
 Bien. Une bonne chose de faite. Pour être sûrs d’être au même niveau, voici le code complet actuel .  
 
 
a. Le titre et le logo de la fenêtre  
 
Nous avons créé la Control Box, mais puisque nous avons enlevé la barre par défaut, le titre a lui aussi disparu. Le logo aussi. Je vous propose d’aller choisir un logo pour votre lanceur. Il y a plusieurs options : 
 
1. Vous avez déjà un logo  
Vous pouvez le convertir si ce n’est déjà fait sur le site ConvertIco. 
 
Attention ›  Un logo de taille 32*32 pixels est très fortement conseillé, si vous réduisez votre logo de 1000*1000 à 32*32, il va être pixelisé et ne rendra pas bien. 
Évitez aussi les ombres, le biseautage, tout ce qui peut faire du relief. Préférez un logo plat. 
 
2. Vous n’avez pas de logo  
Vous pouvez aller en trouver un sur IconFinder  ou prendre un logo Material si vraiment vous n’avez pas d’inspiration. Vous pouvez aussi reprendre le logo de base de Minecraft . 
 
Pour ma part, j’ai pris un logo sur IconFinder , que j’ai converti en icône sur ConvertIco , et j’ai ajouté des marges au fichier original sur Paint .NET . J’suis un mec polyvalent, moi.  
 
   
Figure 15 - Le logo que j'ai choisi pour mon lanceur 
 
Importez votre logo en .PNG dans les ressources de votre lanceur, et créez une PictureBox  à l’intérieur du PNL_TOP , de la même manière que vos étiquettes de Control Box , mais à gauche : 
 
BackColor  à Transparent 
BackgroundImage  à votre image dans les ressources 
BackgroundImageLayout  à Zoom 
Name  à PBX_LOGO – ceci est important 
Dock  à Left 
Size  à 38; 38 
  
Vous avez maintenant un joli logo. Mettez aussi l'image en .ICO dans la propriété Icon  de votre Main . 
On va maintenant ajouter une étiquette qui sera le titre : 
BackColor :  Transparent 
ForeColor :  #bdc3c7  
Ne mettez rien dans Text  
TextAlign :  MiddleLeft 
Name :  LBL_TITLE 
AutoSize :  False 
Dock :   Left 
Size :  300; 38 
  
À noter ›  Mettre une aussi grande largeur est simplement une mesure de précaution. Vous pouvez bien évidemment la réduire. 
 
Rendez-vous dans la fonction Initialize et ajoutez cette ligne : Me .LBL_TITLE.Text = Me .Text . 
Lancez en appuyant sur F5 , et… c’est l’échec ! Si vous avez bien suivi ces étapes, vous ne voyez que la première lettre de votre titre. 
 
Pour faire face à ce problème, nous allons modifier le code avec lequel nous récupérons les polices d’écriture. 
Ajoutez trois fonctions publiques et partagées, avec comme argument optionnel la taille de la police et comme valeur de retour chaque police d’écriture, dans LauncherVariables  : une pour les icônes , les deux autres pour les Roboto  que nous allons importer. 
 
Importez les polices Roboto Regular  et Roboto Medium , téléchargées précédemment, dans votre projet. 
Vous pouvez maintenant modifier votre fonction Initialize  telle que suit : 
 
	Code (vbnet):
	
Private  Sub  Initialize
( ) 
  Try 
    ' Prévention des scintillements 
    Me . SetStyle ( ControlStyles
. AllPaintingInWmPaint  OrControlStyles
. UserPaint  OrControlStyles
. DoubleBuffer , 
True ) 
    ' Modification de la control box 
    Me . LBL_CLOSE . Font  =  LauncherVariables
. MATERIAL_ICONS 
    Me . LBL_CLOSE . Text  =  ChrW ( & HE5CD
) 
    Me . LBL_REDUCE . Font  =  LauncherVariables
. MATERIAL_ICONS 
    Me . LBL_REDUCE . Text  =  ChrW ( & HE5CF
) 
    ' Modification du label titre 
    Me . LBL_TITLE . Font  =  LauncherVariables
. ROBOTO_REGULAR ( 12 ) 
    Me . LBL_TITLE . Text  =  Me . Text 
    ' Affichage en fondu 
    LauncherMethods
. FadeWindow ( Me , FadeAction
. Show , FadeTime
. Fast ) 
  Catch  ex 
As  Exception
    Logger
. Exception ( ex
) 
  End  Try 
End  Sub 
  
 Au cas où, voici le LauncherVariables  actuel (auquel j'ai d'ailleurs ajouté une constante pour la future taille de la bordure) : 
	Code (vbnet):
	 
Public  Class  LauncherVariables 
 
  ' -------------------------------------------------------------------------------------  
  ' ----- [ CONST ] ---------------------------------------------------------------------  
  ' -------------------------------------------------------------------------------------  
 
  Public  Const  DEBUG As  Boolean  =  True  
  Public  Const  BORDER_SIZE As  Integer  =  2  
 
 
  ' -------------------------------------------------------------------------------------  
  ' ----- [ POLICES ] -------------------------------------------------------------------  
  ' -------------------------------------------------------------------------------------  
 
  Public  Shared  Function  MATERIAL_ICONS( Optional  ByVal  Size As  Single  =  15 )  As  Font 
    Return  FontManager. GetFont ( My. Resources . MaterialIcons_Regular , Size)  
  EndFunction 
 
  Public  Shared  Function  ROBOTO_REGULAR( OptionalByVal Size AsSingle =  12 )  As  Font 
    Return  FontManager. GetFont ( My. Resources . Roboto_Regular , Size)  
  EndFunction 
 
  Public  Shared  Function  ROBOTO_MEDIUM( OptionalByVal Size AsSingle =  12 )  As  Font 
    Return  FontManager. GetFont ( My. Resources . Roboto_Medium , Size)  
  EndFunction 
 
EndClass 
 
 Vous lancez votre programme avec F5 , et là… le texte s'affiche, mais pixellisé. Le souci, ici, c’est l’anti-crénelage  (anti-aliasing  en anglais). Par défaut, on ne peut pas modifier la qualité de rendu d’un label. Je vais donc créer un label personnalisé, vous n’êtes pas obligés de le faire. 
 
 
b. Optionnel  - le label personnalisé  
 
Créez un nouveau dossier Custom Controls  et ajoutez-y une class SmoothLabel . Je suis allé piocher un morceau de code assez simple mais plutôt pratique sur Stackoverflow . Pour pouvoir l’utiliser, votre classe doit être partielle , importer System.Drawing.Text  et doit être héritée de Label  (l’héritage est un concept de la POO, si vous ne savez toujours pas ce que c'est, je vous conseille... le tutoriel donné en début de tutoriel :3 ). 
 
	Code (vbnet):
	 
Imports  System. Drawing . Text  
 
Partial  Public  Class  SmoothLabel 
 
  Inherits  Label 
 
  Private  _Hint As  TextRenderingHint =  TextRenderingHint. SystemDefault  
  Public  Property  TextRenderingHint( )  AsTextRenderingHint 
    Get  
      Return  Me . _Hint 
    EndGet 
    Set ( value As  TextRenderingHint)  
      Me . _Hint =  value 
    EndSet 
  EndProperty 
 
  Protected  Overrides  Sub  OnPaint( pe As  PaintEventArgs)  
    pe. Graphics . TextRenderingHint  =  TextRenderingHint 
    MyBase . OnPaint ( pe)  
  EndSub 
 
 Pour ajouter le contrôle, lancez le programme avec F5  et fermez-le. 
Vous pouvez maintenant supprimer l’étiquette LBL_TITLE  et la recréer, mais avec le contrôle SmoothLabel , fraichement ajouté à la boite à outils. 
 
Paramétrez l’étiquette comme précédemment, et vérifiez que le paramètre TextRenderingHint  est bien à AntiAlias . Lancez votre programme : le titre est exactement comme il faut ! 
 
 
c. Des contours  
 
Attaquons-nous aux contours. Ils sont assez important esthétiquement, et assez faciles à dessiner. Il nous faut utiliser GDI+  : nous allons réécrire la fonction OnPaintBackground  afin de dessiner quelque chose. 
 
Je vous laisse ajouter cette fonction, facile à comprendre : 
	Code (vbnet):
	 
  ''' <summary>  
  ''' Se déclenche lors que le fond doit être paint.  
  ''' </summary>  
  Protected  Overrides  Sub  OnPaintBackground( ByVal  e As  PaintEventArgs)  
    MyBase . OnPaintBackground ( e)  
 
    ' Ligne de gauche  
    e. Graphics . FillRectangle ( New  SolidBrush( Me . PNL_TOP . BackColor ) , 
    New  Rectangle(  
    New  Point( 0 , Me . PNL_TOP . Height ) , 
    New  Size( LauncherVariables. BORDER_SIZE , ( Me . Height  -  Me . PNL_TOP . Height ) ) ) )  
 
    ' Ligne de droite  
    e. Graphics . FillRectangle ( New  SolidBrush( Me . PNL_TOP . BackColor ) , 
    New  Rectangle(  
    New  Point( Me . Width  -  LauncherVariables. BORDER_SIZE , Me . PNL_TOP . Height ) , 
    New  Size( LauncherVariables. BORDER_SIZE , ( Me . Height  -  Me . PNL_TOP . Height ) ) ) )  
 
    ' Ligne du bas  
    e. Graphics . FillRectangle ( New  SolidBrush( Me . PNL_TOP . BackColor ) , 
    New  Rectangle(  
    New  Point( LauncherVariables. BORDER_SIZE , ( Me . Height  -  LauncherVariables. BORDER_SIZE ) ) , 
    New  Size( Me . Width  -  ( 2  *  LauncherVariables. BORDER_SIZE ) , LauncherVariables. BORDER_SIZE ) ) )  
  End  Sub  
 
 Vous pouvez voir le résultat en appuyant sur F5 . 
 
 
d. Déplacement de la fenêtre  
 
Vous avez sûrement dû remarquer qu’on ne pouvait pas bouger la fenêtre : cela est dû au fait que nous avons enlevé les bordures par défaut, pour ajouter les nôtres. 
 
Nous allons donc écrire notre propre gestionnaire de déplacement. Créez un nouveau dossier « Managers  » et déplacez-y FontManager . Créez ensuite « MoveManager  ». 
 
Nous devons créer une instance de MoveManager  à chaque fois qu’une nouvelle fenêtre sans bordure s’ouvre. Il lui faut donc un constructeur . 
 
Ce constructeur  devra enregistrer une référence vers la fenêtre  qui l’appelle  ainsi qu’une liste de contrôle  sur lesquels nos clics déplaceront la fenêtre. Il faut donc une variable privée ainsi qu’une boucle dans laquelle nous ajouterons des gestionnaires pour les évènements MouseDown  et MouseMove  : 
 
	Code (vbnet):
	 
  ''' <summary>  
  ''' Instanciation du MoveManager, lié à l'objet LinkedForm  
  ''' </summary>  
  ''' <param name="LinkedForm">La fenêtre à laquelle lier le MoveManager</param>  
  ''' <remarks></remarks>  
  Public  Sub  New ( ByRef  LinkedForm As  Form, ByRef  MoveableControls As  List( OfControl) )  
    Me . _MouseOffset =  NewPoint( 0 , 0 )  
    Me . _LinkedForm =  LinkedForm 
 
    For  Each  MoveableControl AsControl In  MoveableControls 
      AddHandler  MoveableControl. MouseDown , AddressOf  _LinkedForm_MouseDown 
      AddHandler  MoveableControl. MouseMove , AddressOf  _LinkedForm_MouseMove 
    Next  
  End  Sub  
 
 Les évènements MouseDown  et MouseMove  devront permettre de modifier la position de la fenêtre en fonction de notre clic de souris : MouseDown  permettre d’enregistrer un offset  (une distance de compensation ) entre la position du clic  et la position de la fenêtre , et le MouseMove  déplacera la fenêtre en fonction de la position de la souris et de cet offset. 
 
	Code (vbnet):
	 
  ''' <summary>  
  ''' Se déclenche lorsque l'utilisateur maintient un clic sur un contrôle listé  
  ''' </summary>  
  Private  Sub  _LinkedForm_MouseDown( ByVal  sender As  Object , ByVal  e As  MouseEventArgs)  
    _MouseOffset =  New  Point( - ( e. X  +  sender. Location . X ) , - ( e. Y  +  sender. Location . Y ) )  
  EndSub 
 
  ''' <summary>  
  ''' Se déclenche lorsque l'utilisateur déplace sa souris  
  ''' </summary>  
  Private  Sub  _LinkedForm_MouseMove( ByVal  sender As  Object , ByVal  e As  MouseEventArgs)  
    If  e. Button  =  MouseButtons. Left  Then  
      Dim  MousePosition As  Point =  Control. MousePosition  
      MousePosition. Offset ( _MouseOffset. X , _MouseOffset. Y )  
      _LinkedForm. Location  =  MousePosition 
    End  If  
  End  Sub  
 
 Il nous reste à créer une instance de  MoveManager  au démarrage du lanceur. Ajoutez cette ligne dans la fonction Initiate : Dim  MoveManager As New  MoveManager (Me , New  List (Of  Control )(New  Control () {PNL_TOP, LBL_TITLE, PBX_LOGO})). 
 
Ce qui se trouve entre crochets sont les noms des contrôles  que nous autorisons à utiliser pour le déplacement. Si vous avez bien compris, vous savez que vous pourrez désormais déplacer la fenêtre grâce au cadre noir en haut, au logo ainsi qu’au titre de la fenêtre, mais pas grâce à la Control Box . 
 
 
 
 
 
X. L’authentification 
 
Nous sommes des gens bien. Les cracks, c’est pas bien . On ne va pas autoriser les cracks. On pourrait. Mais on ne va pas le faire. 
 
 
a. Préparation 
 
On va déjà commencer par créer les contrôles nécessaires, soit deux zones de texte , une pour le pseudonyme  (ou adresse mail), une pour le mot de passe , et un bouton de validation . 
 
Commencez par ajouter un Panel  à votre Main . Modifiez son nom en PNL_LOGIN , son BackColor  en 153 ; 0 ; 0 ; 0 , son Size  en 300 ; 300 , et son Location  en 84; 172  – ce dernier paramètre est pour centrer verticalement le panel et le rapprocher du bord gauche. 
Changez également son ForeColor  à White . 
 
 
1. Les zones de texte  
 
À noter ›  Je vais expliquer ici comment utiliser une zone de texte transparente. Vous n’êtes pas obligés de suivre ces étapes, et pouvez utiliser une zone de texte normale. 
 
Nativement, il n’est pas possible de rendre transparente une zone de texte . Mais un gentilhomme nous a fourni une bibliothèque disponible ici , qui permet d’intégrer une zone transparente. 
 
Pour l’installer, cliquez-droit sur Tous les Windows Forms  dans la boîte à outils , cliquez sur Choisir les éléments , puis Parcourir , et enfin, sélectionnez AlphaBlendTextBox.dll  là où vous l’avez extrait. Validez en appuyant sur OK , et ajoutez le contrôle qui vient d’apparaître : vous venez d’intégrer une zone de texte transparente . 
 
   
AlphaBlendTextBox est apparu dans la boîte à outils 
 
Pour les autres, vous pouvez simplement prendre une zone de texte normale. Dans les deux cas, appelez cette zone de texte TXT_USERNAME . 
 
Créez un nouveau Panel  et insérez-le dans PNL_LOGIN . Voici ses propriétés : 
 
Name  : PNL_LOGIN_USERNAME 
BackColor  : 153 ; 0 ; 0 ; 0 
Location  : 30; 182 
Size  : 240; 30 
Cursor  : IBeam 
  
Maintenant, placez votre TXT_USERNAME  dans PNL_LOGIN_USERNAME  et centrez-la (location  : 8 ; 9 , et size  : 225 ; 13 ). Cette astuce de type barbare  permet de donner l’impression d’avoir une grande zone de texte. 
 
Faites pareil pour la zone du mot de passe. Le Panel  doit se nommer PNL_LOGIN_PASSWORD  et se trouver en 30 ; 218 . Sa zone de texte doit, elle, avoir le nom TXT_PASSWORD , et la valeur PasswordChar  à « ×  ». 
 
Placez maintenant le code suivant dans la zone destinées aux évènements du Login Panel : 
	Code (vbnet):
	 
    ''' <summary>  
    ''' Se déclenche lorsque l'utilisateur clique sur un panel.  
    ''' </summary>  
    Private  Sub  PNL_LOGIN_USERNAME_MouseClick( sender As  Object , e As  MouseEventArgs)  Handles  PNL_LOGIN_USERNAME. MouseClick  
        TXT_USERNAME. Focus ( )  
    End  Sub  
    Private  Sub  PNL_LOGIN_PASSWORD_MouseClick( sender As  Object , e As  MouseEventArgs)  Handles  PNL_LOGIN_PASSWORD. MouseClick  
        TXT_PASSWORD. Focus ( )  
    End  Sub  
 
 Ce petit bout de code permettre de mettre le focus  sur la zone de texte correspondant à chaque Panel , afin que l'impression de grandeur desdites zones soit totale. 
 
Malheureusement, il est plus compliqué de changer la qualité du texte d’une zone de texte, je ne vais donc pas le voir ici. À la place, je vais mettre la police d’écriture « Segoe UI  » pour les deux zones de texte. 
 
 
 
2. Le bouton de connexion  
 
Certains d’entre vous vont trouver la méthode qui suit barbare, et ils auront raison. Mais c’est le meilleur moyen que j’ai trouvé de faire ce que je voulais (sans passer par GDI+ , évidemment). 
 
Sachez que vous feriez mieux de modifier le fond directement en utilisant GDI+ , mais par simplicité, j’ai choisi ce qui suit : 
 
Créez un SmoothLabel  avec les propriétés suivantes : 
BackColor  : 63 ; 0 ; 0 ; 0 (25% noir) 
Cursor  : Hand 
Font  : Roboto ; 9,25pt 
ForeColor  : 236, 240, 241 
Text  : Connexion 
TextAlign  : MiddleCenter 
Name  : BTN_LOGIN 
Location  : 86;255 
Size  : 129;31 
TextRenderingHint  : AntiAlias 
 Ce label nous servira de bouton de connexion . Je n’ai pas utilisé de bouton, car il serait plus compliqué de modifier son anti-crénelage, alors que notre SmoothLabel  rend exactement comme si c'était un bouton. Autant donc utiliser notre SmoothLabel . 
 
Créez un nouveau Label  (ou SmoothLabel , peu importe) avec les propriétés suivantes : 
BackColor  : 41 ; 128 ; 185 
Font  : Roboto ;9,25pt 
ForeColor  : White 
Text  : vide 
Name  : LBL_LOGIN_UNDERLINE 
Location  : 86; 284 
Size  : 129; 2 
 Vous comprenez ? Cette étiquette va nous servir de bordure inférieure . 
Pour rendre le tout sympathique, ajoutez ceci sous le code déjà présent de la control box : 
 
	Code (vbnet):
	 
  ' -------------------------------------------------------------------------------------  
  ' ----- [ LOGIN PANEL ] ---------------------------------------------------------------  
  ' -------------------------------------------------------------------------------------  
 
  ''' <summary>  
  ''' Se déclenche lorsque la souris entre sur le bouton de connexion.  
  ''' </summary>  
  Private  Sub  BTN_LOGIN_MouseEnter( sender As  Object , e As  EventArgs)  Handles  BTN_LOGIN. MouseEnter  
    Transition. run ( BTN_LOGIN, "ForeColor" , ColorTranslator. FromHtml ( "#ecf0f1" ) , NewTransitionType_Linear( 250 ) )  
    Transition. run ( BTN_LOGIN, "BackColor" , Color. FromArgb ( 154 , 0 , 0 , 0 ) , New  TransitionType_Linear( 350 ) )  
    Transition. run ( LBL_LOGIN_UNDERLINE, "BackColor" , Color. FromArgb ( 154 , 41 , 128 , 185 ) , New  TransitionType_Linear( 500 ) )  
  End  Sub  
  Private  Sub  BTN_LOGIN_MouseLeave( sender As  Object , e As  EventArgs)  Handles  BTN_LOGIN. MouseLeave  
    Transition. run ( BTN_LOGIN, "ForeColor" , Color. White , New  TransitionType_Linear( 250 ) )  
    Transition. run ( BTN_LOGIN, "BackColor" , Color. FromArgb ( 63 , 0 , 0 , 0 ) , New  TransitionType_Linear( 350 ) )  
    Transition. run ( LBL_LOGIN_UNDERLINE, "BackColor" , Color. FromArgb ( 255 , 41 , 128 , 185 ) , New  TransitionType_Linear( 500 ) )  
  End  Sub  
 
 Ouvrez maintenant votre lanceur, et regardez le résultat. Joli, n’est-ce pas ? 
 
Je vais également ajouter deux étiquettes de soulignage sous mes zones de texte. Vous n’êtes pas obligés de le faire, mais si vous le faites, elles auront la même couleur que celle sous le bouton, mais leurs couleurs changeront lors du changement de focus de la zone de texte correspondante : 
 
	Code (vbnet):
	 
  ''' <summary>  
  ''' Se déclenche lorsque la focus entre ou sort du mot de passe.  
  ''' </summary>  
  Private  Sub  TXT_PASSWORD_Enter( sender As  Object , e As  EventArgs)  Handles  TXT_PASSWORD. Enter  
    Transition. run ( LBL_PASSWORD_UNDERLINE, "BackColor" , Color. FromArgb ( 154 , 41 , 128 , 185 ) , New  TransitionType_Linear( 500 ) )  
  End  Sub  
 
  Private  Sub  TXT_PASSWORD_Leave( sender As  Object , e As  EventArgs)  Handles  TXT_PASSWORD. Leave  
    Transition. run ( LBL_PASSWORD_UNDERLINE, "BackColor" , Color. FromArgb ( 255 , 41 , 128 , 185 ) , New  TransitionType_Linear( 500 ) )  
  End  Sub  
 
 De même pour la zone du nom d’utilisateur. 
 
Maintenant que les préparations graphiques sont faites, nous allons passer au script d’authentification. 
 
   
Figure 16 - État actuel du lanceur, un peu vide dans son ensemble 
 
 
 
b. Utilisation de MojangAPI  
 
MojangAPI  est une bibliothèque de classes que j'ai développée dans le cadre de ce tutoriel, afin de faciliter le processus d'authentification auprès des serveurs de Mojang, et en prévention des futures requêtes que nous allons effectuer sur ces mêmes serveurs, notamment pour la récupération du skin. 
 
Je vous invite à télécharger cette bibliothèque sur sa page GitHub  (bouton Télécharger  en haut de l'arborescence). Notez qu'elle est open-source, vous pouvez donc voir l'intérieur de la classe.  
 
 
  
 
Figure 17 - Téléchargement de MojangAPI  
 
Vous n'avez plus qu'à intégrer cette bibliothèque à votre projet.   
 
Rappel ›  pour ajouter une bibliothèque, rendez-vous dans les propriétés du projet (My Project), puis dans références, cliquez sur Ajouter, puis Parcourir..., et trouvez la bibliothèque. 
J'ai simplifié au maximum l'utilisation de cet API afin d'avoir le moins de lignes possible à écrire. 
Je vais expliquer ici comment lancer une requête d'authentification ; si vous voulez plus de détails, jetez un œil dans le readme.md  de la page GitHub  (en anglais).  
 
Vous devez tout d'abord déclarer un objet Request , situé dans l'espace de noms MojangAPI  :   
	Code (vbnet):
	 
Dim  AuthRequest As  New  Request( Request. Method . POST , URL. AUTHENTICATE )  
 
 AuthRequest  étant le nom de la variable de type Request , et les deux arguments étant respectivement le type de requête http  (ici, POST ) et l'adresse de la requête  (ici, l'adresse du serveur d'authentification  avec l'endpoint /Authenticate). 
 
À noter ›  plusieurs adresses sont disponibles dans la classe URL, notamment le Refresh , Validate , Invalidate  et Signout  du serveur d'authentification. 
 
La requête étant maintenant créée, il va falloir l'exécuter : 
	Code (vbnet):
	 
Dim  AuthResponse As  New  AuthenticationResponse(  
      AuthRequest. Execute (  
        Headers. Authenticate ( TXT_USERNAME. Text , TXT_PASSWORD. Text ) ) )  
 
   
Nous avons ici une nouvelle variable AuthResponse  de type AuthenticationResponse , qui contient comme paramètre un texte JSON obtenu grâce à la méthode Execute  de notre type Request , qui lui-même possède comme argument le Header  nécessaire aux requêtes de type POST , qui lui-même contient comme argument le nom d'utilisateur et le mot de passe rentrés dans nos zones de texte. 
 
À noter ›  ceci est juste une explication, nous allons créer un thread pour éviter de geler la fenêtre. De plus, nous devons vérifier le contenu des zones de texte avant d'envoyer la requête. 
 
Le code complet donnerait quelque chose comme ça : 
 
	Code (vbnet):
	 
Dim  AuthRequest As  New  Request( Request. Method . POST , URL. AUTHENTICATE )  
Dim  AuthResponseAs New  AuthenticationResponse( AuthRequest. Execute ( Headers. Authenticate ( TXT_USERNAME. Text , TXT_PASSWORD. Text ) ) )  
 
If  AuthResponseAs . GetResponse . Error  =  Nothing  Then  ' On vérifie si une erreur est survenue  
  ' Si non, nous avons accès aux tokens et au pseudo de l'utilisateur  
  Console. WriteLine ( "AccessToken: "  &  AuthenticationResponse. GetResponse . AccessToken )  
  Console. WriteLine ( "ClientToken: "  &  AuthenticationResponse. GetResponse . ClientToken )  
  Console. WriteLine ( "UserName: "  &  AuthenticationResponse. GetResponse . UserName )  ' Le nom d'utilisateur du joueur. Ce nom n'est pas forcément le contenu de TXT_USERNAME, ce dernier pouvant être une adresse mail  
Else  
  Console. WriteLine ( "Error: "  &  AuthenticationResponse. GetResponse . ErrorMessage )  ' Généralement, un nom d'utilisateur ou mot de passe erroné  
End  If  
 
 Attention ›  ne copiez pas ce code. Je l'ai mis dans un but explicatif ; de toute manière, il ne fonctionnera pas sur votre lanceur car il n'y a pas de console visible. 
 
 
c.  AuthManager et threads [non fonctionnel]  
 
C'est ici que les choses vont se compliquer. 
Si vous avez effectué des tests avec MojangAPI , vous aurez sans doute remarqué qu'une requête est bloquante , car je n'ai pas intégré de multi-threading  dans cette bibliothèque de classes. 
Nous allons donc devoir utiliser notre propre système de multi-threading , afin d'éviter de bloquer l'interface utilisateur lors d'une requête. 
 
À noter ›  si nous effectuons des actions « bloquantes » sur un thread, nous devrons attendre que l'opération soit terminée pour interagir à nouveau avec ce thread. Créer un autre thread permet d'effectuer des actions bloquantes sur ce dernier et de continuer à interagir avec le premier (ici, l'interface). 
 
1. Création de la classe AuthManager  
C'est une classe qui va gérer les authentifications. Nous allons définir un évènement AuthRequestFinished avec comme paramètre un objet AuthentificationResponse (de MojangAPI). 
 
[En cours d'écriture] 
 
 
 
 
 
 Le tutoriel est toujours en cours de rédaction. 
Je passe beaucoup de temps sur sa rédaction, un commentaire ou une appréciation serait la bienvenue :) 
Il ne sera pas finit de si tôt, mais j'avance le plus vite possible. J'attends vos commentaires ! Merci d'avoir lu. :) 
« guillemets »