Le joystick

 

Une librairie sera nécessaire: Winmm.lib pour la dll Winmm.dll

L'include correspondant étant Mmsystem.h, déjà inclus dans windows.h

 

Gestion du joystick par le système

Nombre de joysticks supportés par le driver de joysticks courant

UINT joyGetNumDevs()

En entrée:

Rien

En sortie:

0 Si aucun driver installé, sinon le nombre de joysticks exploitables (mais pas forcement connectés).

 

Lire le joystick

Lecture de la position et de l'état des boutons du joystick

Cette fonctionne retourne les informations concernant un joystick

MMRESULT joyGetPos(
UINT uJoyID,
LPJOYINFO pji
);

En entrée:

uJoyID contient le numéro de joystick à lire (0 à 15). A savoir 0 pouvant être remplacé par JOYSTICKID1, 1 par JOYSTICKID2.

Image non trouvée !Sous NT4, le système ne peut lire que 2 joysticks maximum.

En sortie:

LPJOYINFO pointe sur une structure de type JOYINFO qui contiendra les informations sur l'état du joystick:

typedef struct {
UINT wXpos; // Coordonnées X
UINT wYpos; // Y
UINT wZpos; // Z
UINT wButtons; // Etat des boutons JOY_BUTTON1, JOY_BUTTON2, JOY_BUTTON3, JOY_BUTTON4 pour les boutons de 1 à 4. La valeur retournée est une combinaison des touches actuellement préssées...
} JOYINFO;

MMRESULT contient JOYERR_NOERROR si aucun soucis, mais peut contenir aussi une erreur

Les messages d'erreurs:

Message description
MMSYSERR_NODRIVER Pas de driver joystick
MMSYSERR_INVALPARAM Paramètre invalide passé
JOYERR_UNPLUGGED Le joystick indiqué n'est as connecté

Image non trouvée !Il semble que lorsque le driver peut lire 16 joysticks, alors qu'il n'y a pas assez de ports joysticks (moins de 16), un autre code erreur est généré sur ces ports absents. Mais je ne connais pas la valeur "Microsoft".

 

Pour allez plus loin, il y a la fonction joyGetPosEx() qui retourne encore plus d'informations pour les joysticks spéciaux, cherchez chez Microsoft...Donc faire un et logique pour voir si une touche est effectivement pressée.

Voici un exemple de programme application DOS utilisant les fonctions présentées:

Image non trouvée !

 

 

Caractéristiques d'un joystick

Il est possible de récupérer des informations sur le joystick

La fonction joyGetDevCaps() qui prends trois paramètres,

MMRESULT joyGetDevCaps(
UINT_PTR uJoyID,
LPJOYCAPS pjc,
UINT cbjc
);

En entrée:

uJoyID qui est toujours le même identifiant du joystick pour lequel ont désire des informations (de 0 à 15 sauf pour NT4 blabla. A savoir 0 pouvant être remplacé par JOYSTICKID1, 1 par JOYSTICKID2).

pjc pointeur sur une structure de type JOYCAPS qui va contenir les informations

cbjc Taille de la structure

En sortie:

Renvoie JOYERR_NOERROR si tout se passe bien. ou:

Message description
MMSYSERR_NODRIVER Pas de driver joystick
MMSYSERR_INVALPARAM Paramètre invalide passé

 

Le pointeur utilisé pointe sur une structure définie de la manière suivante:

Comme vous pouvez le voir, le système peut travailler avec des manettes très complètes au niveau des options ! Peut-on encore appeler cela un joystick ?

Type Nom du champ description
WORD wMid ID du manufacteur
WORD wPid ID du produit
TCHAR szPname[MAXPNAMELEN] nom du produit
UINT wXmin valeur minimale de l'axe X
UINT wXmax valeur maximale de l'axe X
UINT wYmin valeur minimale de l'axe Y
UINT wYmax valeur maximale de l'axe Y
UINT wZmin valeur minimale de l'axe Z (Pour accélérer ou mettre les gaz)
UINT wZmax valeur maximale de l'axe Z (Gaz) (Pour accélérer ou mettre les gaz)
UINT wNumButtons nombre de boutons du périphérique
UINT wPeriodMin Période minimale à utiliser lors de la capture (Voir la suite... joySetCapture pour uPeriod)
UINT wPeriodMax Période maximale à utiliser lors de la capture
UINT wRmin valeur minimale de l'axe R (palonniers pour la gouverne de direction d'un avion)
UINT wRmax valeur maximale de l'axe R (palonniers)
UINT wUmin valeur minimale de l'axe U
UINT wUmax valeur maximale de l'axe U
UINT wVmin valeur minimale de l'axe V
UINT wVmax valeur maximale de l'axe V
UINT wCaps Drapeaux indiquant ce que peut gérer le périphérique, voir les valeurs possibles après
UINT wMaxAxes Nombre d'axes que le joystick peut gérer
UINT wNumAxes Nombre d'axes actuellement utilisés
UINT wMaxButtons Nombre de boutons que le joystick peut gérer
TCHAR szRegKey[MAXPNAMELEN] Clé du registre associée au joystick
TCHAR szOEMVxD[MAX_JOYSTICKOEMVXDNAME] Nom du driver du joystick

 

Voici les flags pour wCaps:

JOYCAPS_HASZ Joystick gère des coordonnées sur l'axe Z, soit 3 axes
JOYCAPS_HASR Joystick gère 4 axes (R)
JOYCAPS_HASU Joystick gère 5 axes (U).
JOYCAPS_HASV Joystick gère 6 axes (V).
JOYCAPS_HASPOV Joystick gère les informations point-of-view.
JOYCAPS_POV4DIR Joystick point-of-view indique les informations avant, centrée, arrière, droite et gauche (centered, forward, backward, left, and right).
JOYCAPS_POVCTS Joystick point-of-view en degrés

Capturer le joystick

Problème, sous Windows, nous nous serions attendus à traiter le joystick à l'aide de messages non ?

Et bien, c'est possible, mais il faut que notre fenêtre Windows capture le joystick.

La capture du joystick permet de récupérer les informations du joystick de deux manières: soit le système nous informe périodiquement , soit uniquement à partir d'un changement de l'état du joystick.

 

joySetCapture() va nous permettre la capture du joystick, cette capture indiquera au système qu'il peut envoyer des messages concernant le joystick sous forme plus conventionnelle.

MMRESULT joySetCapture(
HWND hwnd,
UINT uJoyID,
UINT uPeriod,
BOOL fChanged
);

En entrée:

hwnd, le handle de la fenêtre demandant la capture.

uJoyID, l'identifiant du joystick (celui que nous avaons vu précédemment, de 0 à 15 ou encore JOYSTICKID1, ... sachant que NT4 n'en gère que 2 au maximum

uPeriod, fréquence de maj en milliseconde, si les valeurs ne sont pas dans l'intervale préconisé par le joystick, Windows réadaptera automatiquement cette valeur.

fChanged Si à vrai, indique au système que nous désirons être informé à chaque changement d'état de la manette, sinon, nous serons informés systématiquement tous les uPeriod.

 

En sortie JOYERR_NOERROR si absence d'erreur, sinon:

 

Message description
JOYERR_NOERROR Pas d'erreur !
MMSYSERR_NODRIVER Pas de driver joystick
JOYERR_UNPLUGGED Pas de joystick connecté !
JOYERR_PARMS (NT/200/XP) ID invalide ou handle de la fenêtre NULL
JOYERR_NOCANDO (95/98/ME) ID invalide ou handle de la fenêtre NULL
MMSYSERR_INVALPARAM Paramètre invalide passé

 

Si vous utilisez la fonction précédente pour n'être informé que lors des changement d'état (fChanged à true), il peut alors être intéressant d'utiliser les fonctions suivantes: joySetThreshold() ou joyGetThreshold().

En effet, les joysticks en position neutre peuvent retourner des changements d'état alors que vous n'y touchez pas ! Ces différences de positions sont légères, mais il peut être nécessaire de les oublier afin que l'objet graphique sur votre écran n'est pas la tremblote !

Avec ces fonctions Vous allez pouvoir indiquer ( joySetThreshold()) ou lire ( joyGetThreshold()) l'amplitude minimale de mouvement sur un axe à partir de laquelle on considère qu'il y a changement d'état.

Ces fonctions devant être lancées avant réception des messages de changement d'état.

MMRESULT joySetThreshold(
UINT uJoyID,
UINT uThreshold
);

En entrée:

uJoyID, l'identifiant du joystick (celui que nous avaons vu précédemment, de 0 à 15 ou encore JOYSTICKID1, ... sachant que NT4 n'en gère que 2 au maximum

uThreshold, Valeur minimal indiquant un changement

 

En sortie JOYERR_NOERROR si absence d'erreur, sinon:

Message description
JOYERR_NOERROR Pas d'erreur !
MMSYSERR_NODRIVER Pas de driver joystick

ET son équivalent en lecture:

MMRESULT joyGetThreshold(
UINT uJoyID,
LPUINT puThreshold
);

 

Libérer un joystick

Pour libérer un joystick que nous avons capturé, il suffit que la fenêtre soit détruite (libération automatique) ou que vous autorisiez sa libération avec la fontion suivante:

MMRESULT joyReleaseCapture(
UINT uJoyID
);

Avec en entrée le n° d'identifiant du joystick que je ne présente plus ...

En sortie un éventuel code erreur genre:

Message description
MMSYSERR_NODRIVER Pas de driver joystick
MMSYSERR_INVALPARAM Paramètre invalide passé
JOYERR_PARMS Paramètre incorrect

 

Les messages

MM_JOYxBUTTONDOWN Un bouton a été pressé
MM_JOYxBUTTONUP Un bouton a été relaché
MM_JOYxMOVE La position de l'axe X ou Y a changé
MM_JOYxZMOVE La position de l'axe Z a changé

avec x a remplacer par 1 ou 2

Voici donc un premier défaut que l'on constate: La capture des joysticks se limite aux deux premiers. Impossible de traiter les autres joysticks de cette manière. En même temps, il doit être rare de voir plus de deux joysticks sur un PC...

Le second, c'est que les évènements retournés ne traitent pas tous les cas possibles des joysticks (cf. Caractéristiques d'un joystick).

Pour aller plus loin, il faudra donc se passer de ces évènements et trouver une autre solution !

Revenons à nos messages:

Concernant les messages sur les boutons (MM_JOYxBUTTONDOWN et MM_JOYxBUTTONUP): wParam contient les drapeaux pour indiquer l'état des boutons JOY_BUTTONxCHG (changement d'état) et JOY_BUTTONx (bouton pressé) avec x compris entre 1 et 4. LOWORD(lParam) contient la coordonnée X et HIWORD(lParam) la coordonnée Y.

Pour le message MM_JOYxMOVE: wParam contient les drapeaux pour indiquer l'état des boutons JOY_BUTTONx (bouton pressé) avec x compris entre 1 et 4. LOWORD(lParam) contient la coordonnée X et HIWORD(lParam) la coordonnée Y.

Pour le message MM_JOYxZMOVE: LOWORD(lParam) contient la coordonnée Z.

 

 

Voici un exemple sous Windows

Image non trouvée !

Dans cet exemple, je capture le joystick et demande des informations que lors du changement d'état de celui-ci. Ma très vieille manette fonctionnant de la manière suivante: axe X: 0 pour gauche, 32768 centre et 65535 pour droite. Vu le peu de stabilité (+ ou - 100), j'utilise la fonction joySetThreshold en positionnant la valeur à 5000, ce qui effacera largement le défaut ! Même chose pour l'axe Y.

L'écran affiche ensuite les positions en axe X et Y, ainsi que l'état des boutons.

 

Pour aller plus loin

Pour pouvoir traiter l'ensemble des caractéristiques de votre joystick, il faudra utiliser la fonction joyGetPosEx().

MMRESULT joyGetPosEx(
UINT uJoyID,
LPJOYINFOEX pji
);

En entrée:

uJoyID, l'identifiant du joystick (celui que nous avaons vu précédemment, de 0 à 15 ou encore JOYSTICKID1, ... sachant que NT4 n'en gère que 2 au maximum

pji un pointeur sur une structure JOYINFOEX.

En sortie:

pji pointe sur la structure et JOYERR_NOERROR si absence d'erreur, sinon code erreur:

Message description
MMSYSERR_NODRIVER Pas de driver joystick
MMSYSERR_BADDEVICEID N° ID incorrecte !
JOYERR_UNPLUGGED Pas de joystick connecté !
MMSYSERR_INVALPARAM Paramètre invalide passé
JOYERR_PARMS Paramètre incorrect

 

Je n'ai jamais essayé cette fonction, donc pour le moment, je n'en dirais pas plus...

Ils en parle sur internet: http://tcharles.developpez.com/joystick/#interrogation Voir paragraphe IV. L'interrogation du Joystick

 

 

Calibrage du joystick

Ce n'est pas notre rôle ! Il s'agit typiquement d'une opération qui doit être faite par le système d'exploitation. Nous n'avons donc pas à intervenir là dessus ! En effet, le calibrage est valable pour le joystick et pour toutes les applications !

Si vous tenez quand même à avoir une option sur le calibrage, vous pouvez essayer ceci:

WinExec("control joy.cpl", SW_NORMAL);

qui lancera le programme de calibrage tel que vous pourriez le lancer depuis le panneau de configuration.

 

Site intéressant

Developper.com En français, les explications sont claires.