Texel
DirectX | Index | Contact

Le clavier



Téléchargez un code source pour ce tutorial ICI.

Pour utiliser le clavier avec Direct Input, il faut passer par ces étapes:

1.Créer un objet DirectInput : Cet objet est l'interface principale qui permet d'utiliser une ou plusieurs unités d'entrées.
2.Créer un objet DirectInputDevice : Cet objet représente une unités d'entrées. Si votre programme utilise le clavier et la souris, vous devez créer deux de ces objets (un pour le clavier et un pour la souris).
3.Définir un format de donné pour l'objet DirectInputDevice : Cette opération vous permet de définir le nom des constantes qui représenteront chaques touches (exemple: DIK_UP représente la touche flèche haut). Nous n'expliquerons que le format de donné standard, mais il est possible de s'en créer un personnalisé.
4.Définir le comportement de l'unité d'entée : C'est à dire définir son niveau de coopération (pour donnée l'accès exclusif de l'unité à notre application ou bien pour permettre à d'autres applications de l'utiliser) .
5.Obtenir un accès à l'unité d'entrées.
6.Récupérer les informations du clavier : Comme l'appui sur une touche.
7.Libérer toutes les interfaces DirectInput

Important: N'oublier pas dans vos programmes d'inclure "dinput.h", de rajouter la ligne #define INITGUID devant l'inclusion des fichiers ( pour les identificateurs GUID), et de linker la librairie dinput8.lib.




Etape 1: Création d'un objet DirectInput

Après avoir déclarer un objet DirectInput de type LPDIRECTINPUT8 en variable globale, on appel la fonction suivante:

HRESULT WINAPI DirectInput8Create(
  		HINSTANCE hinst,	// handle d'instance de l'application
  		DWORD dwVersion,	// numéro de version de DirectInput souhaité
  		REFIID riidltf,		// identifiant de l'interface désirée
		LPVOID* ppvOut,		// pointeur vers pointeur d'objet DirectInput
		LPUNKNOWN punkOuter  	// pour des agrégats COM
		);











Le deuxième paramètre est une constante pour le numéro de la version de DirectInput que l'on désire utiliser. On lui passe simplement la constante DIRECTINPUT_VERSION pour utiliser la dernière version.

Le troisième paramètre est nouveau dans DirectX 8. C'est l'identifiant du numéro de version de l'interface DirectInput désiré. Son utilité par rapport au paramètre précédant n'est pas très claire.

Le quatrième argument est l'objet DirectInput que nous avons déclarer en variable globale.

Le dernier paramètre prend la valeur NULL dans la très grande majorité des cas.

L'interface que nous venons de créer possède plusieurs méthodes dont:
CreateDevice(): Pour Créer une unité d'entrée
EnumDevices(): Pour détecter les périphériques installés
GetDeviceStatus(): Pour détecter si le périphérique est connecter au PC
RunControlPanel(); Lance le panneau de configuration standard
Release(); Libère l'interface

Attention: Si vous utilisez plusieurs unités d'entrer gérer par DirectInput dans votre programme, vous n'avez besoin de créer qu'un seul objet DirectInput (contrairement aux objets DirectInputDevice).

Si vous devez utiliser DirectX 7, remplacez les interfaces par LPDIRECTINPUT et LPDIRECTINPUTDEVICE et utilisez la fonction suivante:
HRESULT WINAPI DirectInputCreate(
  		HINSTANCE hinst,	// handle d'instance de l'application
  		DWORD dwVersion,	// numéro de version de DirectInput souhaité  		
		LPVOID* ppvOut,		// pointeur vers pointeur d'objet DirectInput
		LPUNKNOWN punkOuter  	// pour des agrégats COM
		);













Etape 2: Créer un objet DirectInputDevice

Partant du principe que l'utilisateur à un clavier (pour savoir comment détecter la présence d'une unité d'entrée allez lire le tutorial sur le joystick), on appel la méthode IDirectInput8::CreateDevice de l'interface DirectInput que l'on vient de créer.

HRESULT CreateDevice(
  		REFGUID rguid,				//identificateur GUID de l'unité à créer
  		LPDIRECTINPUTDEVICE *lplpDirectInputDevice,  	// l'objet
  		LPUNKNOWN pUnkOuter				// pour des agrégats COM = NULL
		);









Pour le clavier le premier argument est GUID_SysKeyboard.
Le deuxième argument est l'objet DirectInputDevice déclarer une variable globale et de type LPDIRECTINPUTDEVICE




Etape 3: Définir un format de donné pour l'objet DirectInputDevice

Pour définir le format de donné, on utilise cette méthode :
HRESULT SetDataFormat(
  		LPCDIDATAFORMAT lpdf
		);








L’argument est soit une structure de type DIDATAFORMAT (pour un format de donné personnalisé) soit la variable prédéfini :c_dfDIKeyboard (pour utiliser le format de donné standard).

Si vous choisissez d’utiliser un format de donné personnalisé, vous devez remplir la structure (lisez pour ça la doc du SDK).

Si vous utilisez le format de donné standard, chaque touche aura une constante standard pour les identifier (disponible dans la doc du SDK). Exemple :DIK_UP (flèche haut), DIK_ESCAPE (touche échappe) …




Etape 4 : Définir le comportement de l'unité d'entée

Cette étape s'effectue grâce à la méthode IDirectInputDevice8::SetCooperativeLevel:

HRESULT SetCooperativeLevel(
  		HWND hwnd,  	//handle de la fenêtre principale
  		DWORD dwFlags  	// drapeau pour niveau coopératif
		);








Il ne vaut mieux pas donner un accès exclusif du clavier à nos applications. C’est pourquoi les drapeaux les plus souvent utilisés et combinés sont DISCL_FOREGROUND|DISCL_NONEXCLUSIVE.




Etape 5 : Obtenir un accès à l'unité d'entrées.

La méthode IDirectInputDevice8::Acquire suffit. Elle n’a pas d’arguments.
Cette acquisition sera perdu si votre fenêtre n'est plus active. Il vous faut donc gérer ce problème avec le message WM_ACTIVATE de votre procédure de fenêtre (cf. code source).




Etape 6 : Récupérer les informations du clavier

Les cinq étapes précédentes se faisaient à l’initialisation. La suite se fait dans la boucle de jeu.
Pour récupérer l’état de chaque touche du clavier à un moment précis, il faut utiliser la méthode IDirectInputDevice8::GetDeviceState.

HRESULT GetDeviceState(
  		DWORD cbData,	// taille du buffer
  		LPVOID lpvData 	// adresse du buffer
		);








Avec cette méthode, l’état de chaque touche du clavier est stocker dans un buffer qui est simplement un tableau de 256 cases.

Dans l’étape 3, je vous ai dis que chaques touches étaient représentées par une constante. Cette dernière remplace en fait le numéro de la case du buffer (qui est un tableau) dans laquelle l’état de la touche est stocker. Le bit le plus important de chaques case du buffer indique si la touche est enfoncée ou non. Donc pour savoir si une touche est enfoncée, on utilise l’opérateur AND avec la valeur hexadécimale 0x80 :
if ( buffer[DIK_UP] & 0x80 )
		// la touche flèche haut est enfoncée







Microsoft suggère dans son SDK l’utilisation de la macro suivante :

#define KEYDOWN(name, key) (name[key] & 0x80)





Très pratique, elle permet de détecter l’appuis d’une touche ainsi :
if ( KEYDOWN( buffer, DIK_UP)
		// la touche flèche haut est enfoncée







Attention: ne récupérer les infos du clavier que si vous y avez accès.



Etape 7 : Libérer toutes les interfaces DirectInput

Avant la fermeture de l’application il ne faut surtout pas oublier:
1.De « déacquérir » les interfaces DirectInputDevice par la méthode IDirectInputDevice8::Unacquire (sans argument).
2.De libérer les interfaces DirectInputDevice par la méthode IDirectInputDevice8::Release (sans argument).
3.De libérer l'objet DirectInput.



Version originale: Avril 2001
Dernière mise à jour: Juin 2002
Par Grégory Smialek
www.texel.fr.fm