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.
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é |
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:
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
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.