Pour manipuler une console, il faut recourir aux fonctions dédiées de l'API Win32.
Celles-ci ont besoin d'un handle sur la console à personnaliser. Hors, même dans le cas d'un programme console disposant dès son lancement d'une console, ce handle n'est pas disponible et doit être récupéré.
Donc, la seule différence entre un programme GUI et un programme console pour la suite des évènements est que le programme GUI doit se charger de créer une console et de la détruire une fois qu'il n'en a plus besoin.
Créer une console
AllocConsole créé une console, initialise les handle stdin, stdout , stderr et l'associe au processus.
Un processus ne peut avoir qu'une seule console.
Détruire une console
FreeConsole
Récupérer un handle sur la sortie standard
Pour modifier le comportement de la console, il est nécessaire d'avoir un handler sur la sortie standard.
En programmation Win32, celui-ci est obtenu via un appel à GetStdHandle.
HANDLE hStdOut =
GetStdHandle( STD_OUTPUT_HANDLE );
Il est aussi possible de récupérer ce handle depuis stdout ou cout. Les fonctions à utiliser sont spécifiques à chaque bibliothèque standard fournie avec les différents compilateurs.
Sous Windows, il s'agit généralement de celle de Microsoft à savoir msvcrt.dll (cas de VC++, LCC).
Celle-ci permet d'obtenir le handle système associé au handle interne de la bibliothèque au moyen de _get_osfhandle.
HANDLE hStdOut = (HANDLE)_get_osfhandle( stdout );
Modifier la couleur du texte affiché
SetConsoleTextAttribute(hStdOut, attributs);
attribut peut être une combinaison des flags suivants :
couleur du texte :
- FOREGROUND_BLUE
- FOREGROUND_GREEN
- FOREGROUND_RED
- FOREGROUND_INTENSITY
couleur de fond :
- BACKGROUND_BLUE
- BACKGROUND_GREEN
- BACKGROUND_RED
- BACKGROUND_INTENSITY
A partir du bleu, rouge, vert, et de l'attribut couleur intense, on peut obtenir les 16 couleurs du mode VGA (exemples avec FOREGROUND, mais biensûr identiques avec BACKGROUND) :
Couleur | Flags |
noir | 0 (aucun flag) |
blanc | FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED |
bleu | FOREGROUND_BLUE |
rouge | FOREGROUND_RED |
vert | FOREGROUND_GREEN |
marron | FOREGROUND_RED | FOREGROUND_GREEN |
fuchsia | FOREGROUND_RED | FOREGROUND_BLUE |
cyan | FOREGROUND_GREEN | FOREGROUND_BLUE |
gris | FOREGROUND_INTENSITY |
blanc intense | FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_INTENSITY |
bleu vif | FOREGROUND_BLUE | FOREGROUND_INTENSITY |
rouge vif | FOREGROUND_RED | FOREGROUND_INTENSITY |
vert vif | FOREGROUND_GREEN | FOREGROUND_INTENSITY |
jaune | FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_INTENSITY |
fuchsia vif | FOREGROUND_RED | FOREGROUND_BLUE | FOREGROUND_INTENSITY |
cyan vif | FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY |
Intercepter la fermeture de la console
Chaque console créée par Windows se voit associée une fonction d'interception du signal de fermeture de console par défaut.
Cette fonction termine le programme s'exécutant dans la console.
Elle est appelée suite à un CTRL-C, un CTRL-BREAK, une fermeture de la console par l'utilisateur
(par le menu ou le gestionnaire de tâches), une fin de session (déconnexion de l'utilisateur)
ou un arrêt/redémarrage de l'ordinateur.
Pour empêcher cela, il faut remplacer cette fonction (handler routine) par défaut à l'aide de SetConsoleCtrlHandler.
Cette fonction doit avoir le prototype suivant : BOOL HandlerRoutine( DWORD CtrlType );
Le paramètre CtrlType permet de connaître l'origine de la demande de fermeture du programme.
La fonction renvoie un booléen indiquant si elle a traîté le signal ou non.
Si ce n'est pas le cas, le gestionnaire par défaut sera appelé et provoquera la fin du processus.
L'appel d'un gestionnaire provoque est effectué dans un thread séparé du thread principal, spécialement créé pour gérer l'interruption.
Une application console, typiquement monothreadée, peut donc devenir multithreadé.
Cela peut provoquer de mauvaises surprises, en particuliers avec les programmes C standards qui sont monothreadés.
Pour éviter les problèmes, la libraririe C standard ne prend pas en compte le signal SIGINT sous Windows.
Effecuer un appel à signal dans cette optique sera donc sans effet.
Il en est de même avec les signaux SIGILL, SIGSEGV, et SIGTERM qui ne sont jamais générés sous Windows NT.
Changer le titre de la console
Ceci est fait au moyen de la fonction SetConsoleTitle.
Récupérer un handle sur la fenêtre de la console
Jusqu'à Windows 2000, Win32 ne disposait pas de fonction permettant d'obtenir le handle de la fenêtre de la console rattachée à son processus.
Il faut alors recourir à FindWindow.
Ce n'est cependant pas si simple car la classe des fenêtres de consoles n'est pas la même sous NT ou Win9x ("ConsoleWindowClass"/"tty"), et il faut identifier le titre de la console associée à son programme.
Un article de la base de connaissances traîte de ce point et donne une solution.
Si vous ne visez que Windows 2000 et supérieur, vous pouvez utiliser
GetConsoleWindow.
Afficher la console en plein écran
fullscr.txt
Rediriger les flux d'Entrée/Sortie de sa console
Rediriger les flux d'E/S de sa propre consle est assez facile.
Il suffit d'appeler SetStdHandle en précisant le flux à rediriger (STDIN, STDOUT, STDERR) et le handle de redirection à utiliser (typiquement un fichier ou un pipe).
Rediriger les flux d'Entrée/Sortie d'une autre console
Rediriger le flux d'une autre console (donc de celle d'un autre processus) nécessite de recourir à un pipe.
Si vous redirigez l'ensemble des flux d'une console a déjà été créée, cette dernière restera visible, bien qu'elle perde toute utilité.
Si vous voulez faire disparraître la console d'un programme CUI et interragir avec lui en regirigeant ses flux
(typiquement pour piloter un programme CUI depuis un programme GUI), c'est à votre programme de créer le processus CUI en lui faisant hériter vos propres flux
ce qui ne provoquera pas la création d'une console.