-- Page de code de ce fichier : Windows Europe de l'ouest -- Tabulation : 3 -- Informations : les-ziboux@rasama.org with ANSI_Console; use ANSI_Console; procedure Test_ANSI is -- ---------------------------------------------------------------------------- -- Programme de test, et exemple d'utilisation du package ANSI_Console -- Système de fenêtrage très simple et basique. -- ---------------------------------------------------------------------------- -- Ce programme utilise le package ANSI_Console que vous pouvez obtenir -- à l'adresse suivate : -- http://www.les-ziboux.rasama.org/ada-commandes-echappement-ansi.html -- -- Ce programme n'est qu'un petit programme de teste, et n'est donc pas -- très commenté. -- -- Lundi 27 novembre 2006 - france (quelque part dans l'est) -- ---------------------------------------------------------------------------- -- ------------------------------------------------------------------------- -- Configuration de la page de code sous DOS -- ------------------------------------------------------------------------- -- Note : ce programme utilise les caractères de cadre ASCII. Par défaut -- sous Windows 95/XP, la page de code DOS n'affiche pas ces caractères -- de cadre. Si le programme semble ne pas produire l'affichage souhaité, -- éditez alors votre fichier autoexec.bat, et modifiez la commande « mode » -- de manière à ce qu'elle corresponde à ceci (deux lignes) : -- mode con codepage prepare=((437) C:\WINDOWS\COMMAND\ega.cpi) -- mode con codepage select=437 -- Sous DOS, c'est la page de code 437 qui doit être active. -- Si la modification d'autoexec.bat est nécessaire, il vous faudra alors -- redémarrer Windows pour que les modifications prennent effet. Cette -- modification n'affecte pas l'affichage sous Windows, mais seulement la -- page de code active sous DOS. De plus, cette page de code, même sous DOS, -- n'affecte pas les caractères courants (seulement quelques caractères -- spéciaux). -- ------------------------------------------------------------------------- -- À propos de ce programme de test -- ------------------------------------------------------------------------- -- Le package ANSI_Console se suffit à lui-même, et permet déjà la création -- d'applications avec une interface intéressante (déjà beaucoup mieux -- que les austères lignes de commande, qui sont trop la règle dans les -- applications en mode texte). Bien que le package ANSI se suffise déjà -- à lui-même, on peut tout de même être inspiré de créer d'autres -- package encore plus évolués qui utiliserait ces fonctionnalité. On peut -- penser à un système de fenêtrage. Créer un tel système demande du -- travail, et ce programme de test ne prétend pas en faire tant. Ce -- programme d'exemple et donc limité : par exemple, il n'y a aucune -- gestion de la superposition des fenêtre, et il n'y a pas non plus de -- prise en charge du passage à la ligne automatique pour l'affichage du -- texte dans une fenêtre, les fenêtres ne peuvent pas être déplacées, etc. -- Deux autres packages verront le jour à l'avenir (à une date -- indéterminée... si vous avez un intérêt dans de tels packages, toutes -- propositions de parrainages sont les bienvenues - contact : -- les-ziboux@rasama.org). -- ------------------------------------------------------------------------- -- Le code du programme commence ici -- ------------------------------------------------------------------------- -- Note : dans les systèmes graphiques, on a l'habitude avec les -- coordonnées, de donner d'abord la coordonnée horizontal, puis ensuite la -- vertical (x,y). Mais dans les systèmes en mode texte, on fait l'inverse -- (ligne, colonne). C'est ainsi que nous procéderons ici (tout comme dans -- le package ANSI_Console). -- Les procédures ce programme d'exemple supposent un mode d'écran de -- 25 lignes sur 80 colonnes (c'est le mode d'écran standard, mais -- mais il est tout de même fixé par la procédure d'initialisation). subtype Line_Type is Natural range 1..25; subtype Column_Type is Natural range 1..80; subtype Height_Type is Natural range 0..25; subtype Width_Type is Natural range 0..80; -- On défini un type fenêtre très basique, qui correspond simplement -- au spécification d'un rectangle. Les fenêtre sont un cadre, avec -- une pseudo case ferme en haut à droite. La manière de dessiner le cadre -- d'une fenêtre impose des restriction sur leurs dimensions possibles. La -- largeur d'une fenêtre est de 5 au minimum, et la hauteur minimum est 2. subtype Window_Line_Type is Line_Type; subtype Window_Column_Type is Column_Type; subtype Window_Height_Type is Height_Type range 2..25; subtype Window_Width_Type is Width_Type range 5..80; -- La zone cliente d'une fenêtre, la zone qui est à l'intérieur, à -- des dimensions bien sûre inférieur à celle de la fenêtre elle-même. -- La largeur de la zone cliente fait 2 de moins que la largeur de la -- fenêtre, idem pour la hauteur. subtype Client_Line_Type is Window_Line_Type range 1..23; subtype Client_Column_Type is Window_Column_Type range 1..78; subtype Client_Height_Type is Height_Type range 0..23; subtype Client_Width_Type is Width_Type range 0..78; -- On défini maintenant un type fenêtre. -- En plus de ces coordonnées et dimensions, une fenêtre spécifie la -- couleur du cadre, et la couleur de la case ferme. On pourra -- également spécifier le type de cadre. type Frame_Type_Enum is (Single_Line_Frame, Double_Line_Frame); type Window_Type is record L : Window_Line_Type; C : Window_Column_Type; H : Window_Height_Type; W : Window_Width_Type; Frame_Type : Frame_Type_Enum; Frame_Color : Color_Type; Close_Box_Color : Color_Type; end record; -- Window_Type -- Un type zone cliente n'a pas besoin de coordonné, car elle sont -- toujours (1,1). Il n'y aura donc que des dimensions. type Client_Type is record H : Client_Height_Type; W : Client_Width_Type; end record; -- Window_Type Metric_Error : exception; -- Positionnement ou dimensionnement incorrect. -- Les procédure concernée par les dimensions et les coordonnées -- déclenchent Metric_Error dans le cas ou un affichage ne passerait pas -- dans l'écran (ou dans une zone préféfinie). C'est le cas si par -- exemple, sur un écran de 25 ligne sur 80 colonnes, on essais -- d'afficher un texte de 15 caractère de longueur, à la position -- (L:3,C:78), car alors le texte ne tient pas entièrement dans l'écran, -- et cela est alors considéré comme une faute. -- Test si le rectangle défini par (L, C)-(H, W) passe dans l'écran. function Fit_In_Screen ( L : in Line_Type; C : in Column_Type; H : in Height_Type; W : in Width_Type) return Boolean is begin if C < 1 then return False; end if; if (C - 1) + W > 80 then return False; end if; if L < 1 then return False; end if; if (L - 1) + H > 25 then return False; end if; return True; end; -- Test si le rectangle défini par (L, C)-(H, W) passe dans la fenêtre. function Fit_In_Window ( Window : in Window_Type; L : in Line_Type; C : in Column_Type; H : in Height_Type; W : in Width_Type) return Boolean is begin if C < 1 then return False; end if; if (C - 1) + W > Window.W then return False; end if; if L < 1 then return False; end if; if (L - 1) + H > Window.H then return False; end if; return True; end; -- Test si le rectangle défini par (L, C)-(H, W) passe dans la zone -- cliente de la fenêtre. Notez que l'argument est bien une fenêtre, et non -- un type Client_Type. function Fit_In_Client ( Window : in Window_Type; L : in Line_Type; C : in Column_Type; H : in Height_Type; W : in Width_Type) return Boolean is begin if C < 1 then return False; end if; if (C - 1) + W > Window.W - 2 then return False; end if; if L < 1 then return False; end if; if (L - 1) + H > Window.H - 2 then return False; end if; return True; end; -- Au lieu d'afficher caractère par caractère, -- les lignes affiché sont plutôt préparer dans cette chaîne, -- puis afficher d'un bloc. Ceci augmente le confort d'affichage. Draw_Buffer : String (Column_Type); -- Dessine un fond d'espace de travail. Le rectangle défini par -- les coordonnées et les dimensions, est rempli avec un caractère -- spécial. procedure Draw_Desktop_Background ( L : in Line_Type; C : in Column_Type; H : in Height_Type; W : in Width_Type; Color : in Color_Type) is begin if not Fit_In_Screen (L, C, H, W) then raise Metric_Error; end if; for j in 1..W loop Draw_Buffer ((C - 1) + j) := Character'Val(176); end loop; Set_Text_Color (Color); for i in 1..H loop Move_Cursor_To ((L - 1) + i, C); Put (Draw_Buffer (C..(C- 1) + W)); end loop; end; -- Dessine un fenêtre, c'est-à-dire un cadre, un fond rempli d'espace, -- et un bouton « ferme » en haut à droite du cadre. procedure Draw_Window (W : in Window_Type) is type Frame_Component_Enum is ( Top_Left_Corner, Top_Right_Corner, Bottom_Right_Corner, Bottom_Left_Corner, Horizontal_Border, Vertical_Border ); Frame_Component : constant array (Frame_Type_Enum, Frame_Component_Enum) of Character := ( Double_Line_Frame => ( Top_Left_Corner => Character'Val(201), Top_Right_Corner => Character'Val(187), Bottom_Right_Corner => Character'Val(188), Bottom_Left_Corner => Character'Val(200), Horizontal_Border => Character'Val(205), Vertical_Border => Character'Val(186)), Single_Line_Frame => ( Top_Left_Corner => Character'Val(218), Top_Right_Corner => Character'Val(191), Bottom_Right_Corner => Character'Val(217), Bottom_Left_Corner => Character'Val(192), Horizontal_Border => Character'Val(196), Vertical_Border => Character'Val(179))); Client_Background : constant Character := Character'Val (32); Close_Box_Symbol : constant Character := 'X'; -- Pourrait être aussi Character'Val(254) begin if not Fit_In_Screen (W.L, W.C, W.H, W.W) then raise Metric_Error; end if; if W.W < 5 then raise Metric_Error; end if; if W.H < 2 then raise Metric_Error; end if; Set_Text_Color (W.Frame_Color); -- Bottom side Draw_Buffer (W.C) := Frame_Component (W.Frame_Type, Bottom_Left_Corner); for i in 2 .. W.W - 1 loop Draw_Buffer ((W.C - 1) + i) := Frame_Component (W.Frame_Type, Horizontal_Border); end loop; Draw_Buffer ((W.C - 1) + W.W) := Frame_Component (W.Frame_Type, Bottom_Right_Corner); Move_Cursor_To ((W.L - 1) + W.H, W.C); Put (Draw_Buffer (W.C..(W.C - 1) + W.W)); -- Top side Draw_Buffer (W.C) := Frame_Component (W.Frame_Type, Top_Left_Corner); Draw_Buffer ((W.C - 1) + W.W - 3) := '['; Draw_Buffer ((W.C - 1) + W.W - 2) := 'X'; -- Character'Val(254); Draw_Buffer ((W.C - 1) + W.W - 1) := ']'; Draw_Buffer ((W.C - 1) + W.W) := Frame_Component (W.Frame_Type, Top_Right_Corner); Move_Cursor_To (W.L, W.C); Put (Draw_Buffer (W.C..(W.C - 1) + W.W)); -- Middle Draw_Buffer (W.C) := Frame_Component (W.Frame_Type, Vertical_Border); for i in 2 .. W.W - 1 loop Draw_Buffer ((W.C - 1) + i) := Client_Background; end loop; Draw_Buffer ((W.C - 1) + W.W) := Frame_Component (W.Frame_Type, Vertical_Border); for i in 2..W.H - 1 loop Move_Cursor_To ((W.L - 1) + i, W.C); Put (Draw_Buffer (W.C..(W.C - 1) + W.W)); end loop; -- Button Set_Text_Color (W.Close_Box_Color); Move_Cursor_To (W.L, (W.C - 1) + W.W - 2); Put (Close_Box_Symbol); end; -- Dessine un caractère dans la zone cliente d'une fenêtre, aux coordonnées -- spécifiées avec la couleur indiquée. procedure Draw ( W : in Window_Type; L : in Client_Line_Type; C : in Client_Column_Type; Color : in Color_Type; Ch : in Character) is begin -- ((W.L + 1) - 1) + L = W.L + L -- ((W.C + 1) - 1) + C = W.C + C if not Fit_In_Screen (W.L + L, W.C + C, 1, 1) then raise Metric_Error; end if; if not Fit_In_Client (W, L, C, 1, 1) then raise Metric_Error; end if; Set_Text_Color (Color); Move_Cursor_To (W.L + L, W.C + C); Put (Ch); end; -- Dessine du texte dans la zone cliente d'une fenêtre, aux coordonnées -- spécifiées avec la couleur indiquée. procedure Draw ( W : in Window_Type; L : in Client_Line_Type; C : in Client_Column_Type; Color : in Color_Type; Text : in String) is begin -- ((W.L + 1) - 1) + L = W.L + L -- ((W.C + 1) - 1) + C = W.C + C if not Fit_In_Screen (W.L + L, W.C + C, 1, Text'Length) then raise Metric_Error; end if; if not Fit_In_Client (W, L, C, 1, Text'Length) then raise Metric_Error; end if; Set_Text_Color (Color); Move_Cursor_To (W.L + L, W.C + C); Put (Text); end; -- Dessine du texte centré. Comme c'est le centrage qui donne la coordonnée -- horizontal, on ne spécifie bien sûre que la coordonnée vertical. procedure Draw_Centered ( W : in Window_Type; L : in Client_Line_Type; Color : in Color_Type; Text : in String) is C2 : Natural; begin -- (W.L + 1) - 1 = W.L if not Fit_In_Screen (W.L + L, W.C + 1, 1, Text'Length) then raise Metric_Error; end if; if not Fit_In_Client (W, L, 1, 1, Text'Length) then raise Metric_Error; end if; if W.W - 2 < Text'Length then raise Metric_Error; end if; -- (W.C - 1) + 1 = W.C C2 := W.C + (W.W - 2 - Text'Length) / 2; Set_Text_Color (Color); Move_Cursor_To (W.L + L, C2); Put (Text); end; procedure Move_Cursor_To ( W : in Window_Type; L : in Client_Line_Type; C : in Client_Column_Type) is begin if L < 1 then raise Metric_Error; end if; if L > W.H - 2 then raise Metric_Error; end if; if C < 1 then raise Metric_Error; end if; if C > W.W - 2 then raise Metric_Error; end if; Move_Cursor_To (W.L + L, W.C + C); end; procedure Initialize is begin -- Initialisation Set_Screen_Mode (Color_Text_Mode_80x25); Disable_Line_Wrapping; -- Pour éviter les mauvaises surprises d'affichage. Set_Background_Color (Blue); -- La couleur la plus supportable pour un fond. Set_Text_Attributes (Bold_Text); -- Texte en couleur claire. Clear_Screen; -- Évidement... end; procedure Leave_And_Restore_Defaults is begin -- Avant de quitter, on restitue l'environnement Enable_Line_Wrapping; -- En condition normal, toujours Set_Background_Color (Black); -- Couleur normal la plus courante Set_Text_Color (White); -- Couleur normal la plus courante Set_Text_Attributes (Default_Text_Attributes); Clear_Screen; -- Si on effaçais pas, le reste d'écran défilerait : pas joli. -- On ne peut pas restaurer le mode d'écran, car on n'a aucun moyen de -- connaître le mode graphique qui était actif au démarrage. end; W0 : Window_Type := ( -- Fenêtre de test du clavier L => 2, C => 2, H => 4, W => 28, Frame_Type => Single_Line_Frame, Frame_Color => White, Close_Box_Color => Blue); W1 : Window_Type := ( -- Fenêtre qui joue à Windows 3.1 L => 7, C => 5, H => 10, W => 24, Frame_Type => Double_Line_Frame, Frame_Color => Yellow, Close_Box_Color => Red); W2 : Window_Type := ( -- Fenêtre qui joue à Windows XP L => 4, C => 31, H => 14, W => 34, Frame_Type => Double_Line_Frame, Frame_Color => Blue, Close_Box_Color => Cyan); W3 : Window_Type := ( -- Fenêtre d'information L => 19, C => 2, H => 5, W => 78, Frame_Type => Single_Line_Frame, Frame_Color => Yellow, Close_Box_Color => Red); -- Cette fonction est un petit bricolage.. ne pas y prêter attention. function Natural_Image_3 (N : Natural) return String is L : Natural; begin L := Natural'Image (N)'Length; if L = 4 then return Natural'Image (N) (2..4); elsif L = 3 then return "0" & Natural'Image (N) (2..3); else return "00" & Natural'Image (N) (2..2); end if; end; -- Cette boucle d'événement donne un exemple de l'utilisation -- du Get non-bloquant. procedure Old_Events_Loop is -- FIFO des quatre derniers caractères entrés au clavier C1 : Character := Character'Val (0); C2 : Character := Character'Val (0); C3 : Character := Character'Val (0); C4 : Character := Character'Val (0); -- Pour teste et récupération du résultat d'appuie d'une touche C : Character; -- Chaînes pour la représentation numérique des quatre derniers -- caractères saisie au clavier S1 : String(1..3); S2 : String(1..3); S3 : String(1..3); S4 : String(1..3); -- Pour Get non-bloquant Available : Boolean; -- Est-ce qu'une touche était appuyée à la précédente itération ? Previous_Pressed : Boolean; -- Code de la touche « Echap » Touche_Echap : constant Character := Character'Val (27); begin -- Affiche le contenu initial Draw (W0, 1, 1, Blue, "Touche appuyee :"); Draw (W0, 1, 17, Cyan, " ---"); Draw (W0, 2, 1, Cyan, "[--- --- --- ---]"); Move_Cursor_To (W0, 2, 20); -- Previous_Pressed indique si une touche était appuyée à -- l'itération précédente. Previous_Pressed := False; loop Get (C, Available); if Available and C = Touche_Echap then Beep; exit; elsif Available then C1 := C2; C2 := C3; C3 := C4; C4 := C; Draw (W0, 1, 18, Cyan, "Oui"); S1 := Natural_Image_3 (Character'Pos (C1)); S2 := Natural_Image_3 (Character'Pos (C2)); S3 := Natural_Image_3 (Character'Pos (C3)); S4 := Natural_Image_3 (Character'Pos (C4)); Draw (W0, 2, 2, Cyan, S1 & " " & S2 & " " & S3 & " " & S4); Move_Cursor_To (W0, 2, 20); Previous_Pressed := True; elsif Previous_Pressed then -- On ne le fait que si on était pas déjà dans -- cet état lors de l'itération précédente (ceci évite -- de faire flotter l'affichage). Draw (W0, 1, 18, Cyan, "Non"); Move_Cursor_To (W0, 2, 20); Previous_Pressed := False; end if; end loop; end; subtype Key_Title_Type is String (1..9); Key_Title : constant array (Key_Type) of Key_Title_Type := ( Key_F1 => "F1 ", Key_F2 => "F2 ", Key_F3 => "F3 ", Key_F4 => "F4 ", Key_F5 => "F5 ", Key_F6 => "F6 ", Key_F7 => "F7 ", Key_F8 => "F8 ", Key_F9 => "F9 ", Key_F10 => "F10 ", Key_F11 => "F11 ", Key_F12 => "F12 ", Keypad_Home => "KP-Home ", Keypad_Up_Arrow => "KP-Up ", Keypad_Page_Up => "KP-PgUp ", Keypad_Left_Arrow => "KP-Left ", Keypad_Right_Arrow => "KP-Right ", Keypad_End => "KP-End ", Keypad_Down_Arrow => "KP-Down ", Keypad_Page_Down => "KP-PgDn ", Keypad_Insert => "KP-Insert", Keypad_Delete => "KP-Delete", Key_Home => "Home ", Key_Up_Arrow => "Up ", Key_Page_Up => "Page-Up ", Key_Left_Arrow => "Left ", Key_Right_Arrow => "Right ", Key_End => "End ", Key_Down_Arrow => "Down ", Key_Page_Down => "Page-Down", Key_Insert => "Insert ", Key_Delete => "Delete ", Key_Print_Screen => "PrnScreen", Key_Pause_Break => "Pause ", Key_Escape => "Escape ", Key_Backspace => "Backspace", Key_Enter => "Enter ", Key_Tab => "Tab ", Key_Null => "Null ", Key_A => " ", Key_B => " ", Key_C => " ", Key_D => " ", Key_E => " ", Key_F => " ", Key_G => " ", Key_H => " ", Key_I => " ", Key_J => " ", Key_K => " ", Key_L => " ", Key_M => " ", Key_N => " ", Key_O => " ", Key_P => "

", Key_Q => " ", Key_R => " ", Key_S => " ", Key_T => " ", Key_U => " ", Key_V => " ", Key_W => " ", Key_X => " ", Key_Y => " ", Key_Z => " ", Key_0 => "<0> ", Key_1 => "<1> ", Key_2 => "<2> ", Key_3 => "<3> ", Key_4 => "<4> ", Key_5 => "<5> ", Key_6 => "<6> ", Key_7 => "<7> ", Key_8 => "<8> ", Key_9 => "<9> ", Key_Minus => "<-> ", Key_Equal => "<=> ", Key_Left_Square => "<[> ", Key_Right_Square => "<]> ", Key_Space => "< > ", Key_Semicolon => "<;> ", Key_Single_Quote => "<'> ", Key_Comma => "<,> ", Key_Dot => "<.> ", Key_Slash => " ", Key_Left_Single_Quote => "<`> ", Keypad_Enter => "KP-< > ", Keypad_Slash => "KP- ", Keypad_Star => "KP-<*> ", Keypad_Minus => "KP-<-> ", Keypad_Plus => "KP-<+> ", Keypad_Middle => "KP-Middle"); subtype Modifier_Key_Title_Type is String (1..5); Modifier_Key_Title : constant array (Modifier_Key_Type) of Modifier_Key_Title_Type := ( No_Modifier_Key => " ", Alt_Key => " Alt", Ctrl_Key => " Ctrl", Shift_Key => "Shift"); function Is_Printable (C : in Character) return Boolean is begin if Character'Pos (C) in 0..31 then return False; else return True; end if; end; procedure Events_Loop is K : Keystroke_Input_Type; -- Est-ce qu'une touche était appuyée à la précédente itération ? Previous_Pressed : Boolean; begin -- Affiche le contenu initial Draw (W0, 1, 1, Blue, "Touche appuyee :"); Draw (W0, 1, 17, Cyan, " ---"); Draw (W0, 2, 1, Blue, "[C: K: + ]"); Draw (W0, 2, 4, Cyan, '-'); Draw (W0, 2, 8, Cyan, "-----"); Draw (W0, 2, 13, Blue, '+'); Draw (W0, 2, 14, Cyan, "---------"); Move_Cursor_To (W0, 2, 26); -- Previous_Pressed indique si une touche était appuyée à -- l'itération précédente. Previous_Pressed := False; loop Get_Key (K); if K.Character_Available and not Is_Printable (K.C) then K.Character_Available := False; end if; if K.Key_Available and K.Key = Key_Escape then Beep; exit; end if; if K.Character_Available then Draw (W0, 2, 4, Cyan, K.C); if not K.Key_Available then Draw (W0, 2, 8, Cyan, " "); end if; end if; if K.Key_Available then if K.Modifier_Key /= No_Modifier_Key then Draw (W0, 2, 8, Cyan, Modifier_Key_Title (K.Modifier_Key)); Draw (W0, 2, 13, Blue, '+'); Draw (W0, 2, 14, Cyan, Key_Title (K.Key)); else Draw (W0, 2, 8, Cyan, " "); Draw (W0, 2, 13, Blue, ' '); Draw (W0, 2, 14, Cyan, Key_Title (K.Key)); end if; if not K.Character_Available then Draw (W0, 2, 4, Cyan, ' '); end if; end if; if K.Key_Available or K.Character_Available then Draw (W0, 1, 18, Cyan, "Oui"); Previous_Pressed := True; Move_Cursor_To (W0, 2, 26); else if Previous_Pressed then -- On ne le fait que si on était pas déjà dans -- cet état lors de l'itération précédente (ceci évite -- de faire flotter l'affichage). Draw (W0, 1, 18, Cyan, "Non"); Move_Cursor_To (W0, 2, 20); Previous_Pressed := False; Move_Cursor_To (W0, 2, 26); end if; end if; end loop; end; begin Initialize; -- Comme avec Windows, on commence par mettre en place le fond du bureau :P Draw_Desktop_Background (1, 1, 25, 80, Blue); -- Une première fenêtre avec du texte à l'intérieur. Draw_Window (W1); Draw (W1, 1, 1, White, "Coucou! :)"); Draw (W1, 2, 1, White, "Je suis Windows 3.1"); Draw (W1, 3, 1, White, "en mode texte"); Draw (W1, 4, 1, White, "Coooool!"); -- Idem... une deuxième. Draw_Window (W2); Draw (W2, 1, 1, White, "Waaaw, encore mieux"); Draw (W2, 2, 1, White, "Moi j'suis Windows XP"); Draw (W2, 3, 1, White, "... en mode texte aussi :P"); Draw (W2, 4, 1, White, "... le bleu me va si bien"); Draw (W2, 5, 1, White, "... hihihi"); -- Messages pour que l'utilisateur(rice) ne se sente pas perdu(e). Draw_Window (W3); Draw_Centered (W3, 1, Green, "Note : appuyez ALT+Enter pour basculer le plein ecran"); Draw_Centered (W3, 2, Yellow, "Appuyez sur des touches au hasard pour tester leurs codes"); Draw_Centered (W3, 3, Yellow, "Appuyez sur Echap pour quitter"); -- La fenêtre de test du clavier. Draw_Window (W0); -- Exécution. Events_Loop; Leave_And_Restore_Defaults; end;