FAQ Win32
FAQ Win32Consultez toutes les FAQ
Nombre d'auteurs : 11, nombre de questions : 72, dernière mise à jour : 16 juin 2021
- Peut-on créer une fenêtre dans une application console ?
- Peut-on créer une console dans une application fenêtrée ?
- Pourquoi les caractères accentués ne s'affichent-ils pas correctement dans la console ?
- Que font exactement GetStdHandle et SetStdHandle ?
- Comment obtenir un handle vers la console ?
- Comment modifier le titre de la console ?
- Comment positionner le curseur ?
- Comment effacer l'écran ?
Tout comme on peut en créer dans une application GUI.
Bien sûr. Pour créer une console, il suffit d'appeler la fonction AllocConsole. On ne peut avoir qu'une console par processus au plus, qu'il s'agisse d'une application console ou fenêtrée. Pour la fermer, on utilise FreeConsole. En ce qui concerne les entrées/sorties, ... c'est à voir dans les fonctions d'entrées/sorties.
Lien : Que font exactement GetStdHandle et SetStdHandle ?
Lien : Comment obtenir un handle vers la console ?
Car le jeu de caractères utilisé à l'exécution (dans la console) n'est pas le même que celui qui fut utilisé pour créer le fichier source. Votre fichier source a été créé en utilisant le jeu de caractères utilisé par l'environnement graphique, qui est ANSI (CP1252), alors que la console utilise un code OEM (Original Equipement Manufacturer), CP850, afin de faire fonctionner correctement les applications MS-DOS. Il y a plusieurs méthodes permettant de contourner ce problème allant de la conversion du fichier source avant sa compilation (déconseillé) à la configuration de la console par l'application ou l'utilisateur mais la plus simple à comprendre est celle qui consiste à convertir les chaînes à afficher avant de réellement les afficher. Cela se fait à l'aide de la fonction CharToOem.
#include <stdio.h>
#include <windows.h>
int
main
(
)
{
char
s[51
] =
"
Prêt pour l'expérience.
"
, t[51
];
CharToOem
(
s, t);
printf
(
"
%s
\n
"
, t);
return
0
;
}
GetStdHandle permet de récupérer le handle de l'entrée, la sortie ou l'erreur standard. SetStdHandle c'est bien sûr
pour spécifier un nouvel handle. Sous Windows, au niveau des applications, les entrées/sorties se font largement par
l'intermédiaire des "fichiers". Un fichier, ça peut être une console, un tube (pipe), un fichier sur disque, etc.
On peut lire/écrire sur ces fichiers à l'aide des fonctions génériques ReadFile/WriteFile.
Selon le type exact du fichier, on peut également utiliser les fonctions spécifiques
à ce type de fichier. On peut également augmenter le niveau d'abstraction dans l'application en encapsulant un handle par un file descriptor
(voir _open_osfhandle) qui à son tour peut encore être encapsulé par un flux (voir _fdopen).
Voici un programme qui écrit "Hello world !" sur la sortie standard en utilisant WriteFile.
#include <windows.h>
int
main
(
)
{
HANDLE hStdout;
char
s[] =
"
Hello world !
\r\n
"
;
DWORD dwBytesWritten;
hStdout =
GetStdHandle
(
STD_OUTPUT_HANDLE);
WriteFile
(
hStdout, s, (
DWORD)strlen
(
s), &
dwBytesWritten, NULL
);
return
0
;
}
Une console possède deux buffers : un "input buffer" (l'entrée), utilisé pour stocker les entrées de l'utilisateur (une application peut toutefois écrire dans ce buffer ...) et un "screen buffer" (l'écran) utilisé pour gérer l'affichage (cartographie de l'écran, position actuelle du curseur, etc.).
"CONIN$" et "CONOUT$" peuvent être utilisés dans CreateFile comme nom de fichier pour obtenir respectivement un handle vers l'entrée et un handle vers l'écran.
On peut également utiliser "CON" qui ne peut être que soit lu (dans ce cas CreateFile retourne un handle vers l'entrée) soit écrit (on obtient
alors un handle vers l'écran). Si l'entrée, la sortie et/ou l'erreur standard sont attachées à la console, alors GetStdHandle est un autre moyen d'obtenir ces handles (avec les droits GENERIC_READ | GENERIC_WRITE).
Voici donc une fonction qui crée une console puis y affiche "Hello world !", à utiliser dans une application fenêtrée. En outre, il est
supposé que vous avez correctement enregistré une classe de fenêtre nommée "With Console" et écrit la procédure de fenêtre pour cette classe.
int
CreateWindowWithConsole
(
HINSTANCE hInstance)
{
HWND hWnd;
MSG msg;
hWnd =
CreateWindow
(
"
With Console
"
, ""
, WS_OVERLAPPEDWINDOW, 100
, 100
, 100
, 100
,
NULL
, NULL
, hInstance, NULL
);
ShowWindow
(
hWnd, SW_SHOWNORMAL);
if
(
AllocConsole
(
))
{
HANDLE hScreenBuffer;
char
s[] =
"
Hello world !
\r\n
"
;
DWORD dwBytesWritten;
hScreenBuffer =
CreateFile
(
"
CONOUT$
"
, GENERIC_WRITE, 0
, NULL
, OPEN_EXISTING, 0
, NULL
);
WriteFile
(
hScreenBuffer, s, (
DWORD)strlen
(
s), &
dwBytesWritten, NULL
);
while
(
GetMessage
(&
msg, NULL
, 0
, 0
))
{
TranslateMessage
(&
msg);
DispatchMessage
(&
msg);
}
CloseHandle
(
hScreenBuffer);
FreeConsole
(
);
}
return
0
;
}
Pour obtenir un handle vers la fenêtre de la console, utilisez plutôt GetConsoleWindow().
SetWindowText(GetConsoleWindow(), "Ma console") ou tout simplement SetConsoleTitle("Ma console").
A l'aide de la fonction SetConsoleCursorPosition.
void
GotoXY
(
HANDLE hConsoleOutput, SHORT x, SHORT y)
{
COORD P;
P.X =
x;
P.Y =
y;
SetConsoleCursorPosition
(
hConsoleOutput, P);
}
On détermine les dimensions de la console à l'aide de GetConsoleScreenBufferInfo ensuite on la remplit de caractères "espace" en utilisant FillConsoleOutputCharacter. Il faut ensuite remettre le curseur en début de l'écran après que celui-ci ait été effacé.
void
cls
(
HANDLE hConsoleOutput)
{
CONSOLE_SCREEN_BUFFER_INFO screen;
COORD Origin =
{
0
, 0
}
;
DWORD dwScreenSize, dwBytesWritten;
GetConsoleScreenBufferInfo
(
hConsoleOutput, &
screen);
dwScreenSize =
screen.dwSize.X *
screen.dwSize.Y;
FillConsoleOutputCharacter
(
hConsoleOutput, '
'
, dwScreenSize, Origin, &
dwBytesWritten);
SetConsoleCursorPosition
(
hConsoleOutput, Origin);
}