Sylvain Maréchal
Révision le 18/11/2005
Réalisation d'une boîte à outils pour les applications Turbo C++ développées en mode texte
Cette fonction fonctionne comme getch(). Sa particularité est de sortir lorsqu'un temps précisé en argument est écoulé.
Elle peut servir de base à toute application en attente d'un choix de l'utilisateur. Le timeout peut être utilisé pour afficher une animation « en tâche de fond ».
Les versions plus évoluées peuvent être utilisées pour réaliser des jeux simples (Tetris, packman, arkanoid; jeux de tirs, serpent etc...)
long getch_timeout( clock_t timeout )
clock_t timeout : Le temps au bout duquel on sort de la fonction en « tick ». Si l'argument vaut 0, le temps est « infini » (Les tick valent 1/18 de secondes sous turboC)
bits 0 à 7 : Le code ascii de la touche ou 0 s'il s'agit d'une touche étendue
bits 8 à 15 : 0 s'il s'agit d'une touche non étendue, sinon, le code étendu de la touche
bits 16 à 31 : 0 (Réservé pour les évolutions)
On commence par stocker « l'heure de début de la fonction» clockDeb à l'aide de la fonction clock().
On utilise une boucle do {...} while (1);
au sein de cette boucle, on va utiliser la fonction kbit() qui renvoie une valeur non nulle lorsqu'une touche est pressée.
Dans ce cas, on utilise getch() pour extraire le code de touche.
Si le code de touche est nul, alors il s'agit d'une touche étendue et on rappelle getch() afin d'extraire le code étendu.
Dans ces 2 cas, on va renvoyer le code de touche comme indiqué ci-dessus avec return.
Pour mettre le code de touche étendu, on utilise l'opérateur de décalage de bits vers la gauche <<.
Si aucune touche n'a été pressée, on récupére « l'heure actuelle » clockAct.
On soustrait alors clockDeb. Si le temps est supérieur au timeout, on sort de la fonction en renvoyant 0.
On peut utiliser le programme de test suivant (On sort quand on appuie sur Q ou Echap:
int main()
{
while(1)
{
long keyOrTm = getch_timeout(CLOCK_TICK);
if( (char)keyOrTm == 'Q' || keyOrTm == 27 )
{
printf( « On Sort ...\n » );
}
else if( keyOrTm != 0)
{
printf( « Code touche : %d\n », keyOrTm
}
else // keyOrTm == 0
{
printf( « Timeout ecoule » );
}
}
return 0;
}
La fonction précédente a un gros inconvénient. Si on appuie sans arrêt sur des touches, on ne sort jamais en timeout.
Modifier la fonction précédente de manière que l'on sorte de la fonction à chaque fois que le timeout est écoulé, indépendamment de l'appui sur une touche.
On rend la variable clockDeb statique.
On l'initialise avec clock() uniquement quand elle est nulle.
Chaque fois que le timeout est écoulé, on réinitialise clockDeb à 0.
Modifier la fonction précédente afin qu'elle ne réagisse qu'aux touches connues. Ces touches seront communiquées à la fonction à l'aide d'un tableau.
Le nouveau prototype est
long getch_timeout2( clock_t timeout, long touches[], int nbTouches);
Exemple d'utilisation :
// ... Comme précédement
long touches[] = { 27, 'Q' };
int nbtouches =
sizeof( touches) /sizeof(long); // ici, 8 / 4 = 2
long keyOrTm = getch_timeout2(CLOCK_TICK, touches, nbtouches);
// ....
Créer des fonctions permettant d'extraire le code étendu, et le code ascii.
unsigned char code_to_char_ascii( long code );
On utilise l'opérateur binaire & pour mettre les 24 bits de poids forts à 0 et ne conserver que les 8 bits de poids faible.
unsigned char code_to_char_etendu( long code );
On utilise l'opérateur binaire >> pour décaler le code de 8 bits vers la droite, puis on procède comme précédemment pour mettre les 24 bits de poids forts à 0 et ne conserver que les 8 bits de poids faible.
Afin d'être capable de gérer plusieurs animations fonctionnant à des vitesses différentes, on passe à la fonction un tableau de timeout.
Le prototype est
long getch_timeout2( clock_t timeouts[] , int nbtimeouts, long touches[], int nbtouches);
On utilise en interne un tableau statique de 32 valeurs maximum à la place de clockDeb.
Le fonctionnement est exactement le même. On doit maintenant boucler sur ce tableau et trouver si le timeout est écoulé pour l'un des éléments. (On suppose que tous les timeouts sont différents. Si ce n'est pas le cas, on ne s'occupe que du premier rencontré. Dans tous les cas, on ne s'occupe que d'un timeout à la fois).
On utilise les bits 16 à 23 pour stocker le numéro de timeout qui correspond à l'index du tableau pour lequel le timeout est écoulé (soit de 0 à 31)
On procède comme en 2bis pour créer la fonction
unsigned char code_to_index_timeout( long code );
Le but est de créer des outils réutilisables dans les applications.
Créer une fonction void affiche_menu( char * tabmenus[], int nbmenus )
char * tabmenus[] : Les libellés des menus à afficher
int nbmenus : Le nombre de libellés
Afin d'indiquer à l'utilisateur quelle touche il doit presser, on mettra pour chaque libellé la première lettre majuscule rencontrée en rouge, les autres lettres étant affichées en noir sur fond gris.
Cette fonction peut être utilisée dans les fonctions suivantes.
void affiche_ombre( int x, int y, int largeur, int hauteur)
Explications détaillées à venir ...
void affiche_titre( int y, const char * titre )
Explications détaillées à venir ...
void affiche_fond( char c, int color )
Explications détaillées à venir ...
struct entete_infos
{
char ** titres_colonne;
int nbcolonnes;
};
struct ligne_infos
{
char ** valeurs_cellules;
int nbcellules
};
struct tableau_infos
{
ligne_infos * tabligneinfos;
int nblignes;
};
void affiche_tableau( entete_infos ei, tableau_infos ti );
Explications détaillées à venir ...
struct saisie_infos
{
char libelle[20];
char valeur[20];
};
void fenetre_saisie( saisie_infos si[], int nbsi );
Explications détaillées à venir ...