2 votes

Comment implémenter un code Joystick en C++ en utilisant l'IDirectInputDevice8 de Microsoft ?

Je dois faire du blocage et du non blocage blocage appelle pour interroger un périphérique d'entrée directe en utilisant IDirectInputDevice8 interface.

Dans linux pour faire le blocage, nous utilisons sélectionnez ex :

while( ::select(_jdev+1, &set, NULL, NULL, &tv) > 0) 
{
    if( ::read( _jdev, &js, sizeof( js_event ) ) != sizeof( js_event ) )
    {
        perror( "Joystick : read error" );
        return;
    }

    _handleEvent( js );
}

Comment puis-je faire la même chose en utilisant le dispositif d'entrée indirecte8 interface : https://msdn.microsoft.com/en-us/library/Windows/desktop/ee417816(v=vs.85).aspx

Même si j'ai mis IDirectInputDevice8::SetEventNotification() Je dois toujours appeler poll() à chaque fois pour récupérer les nouvelles données et ce n'est pas une solution viable car cela fait tourner le processeur.

Comment puis-je y parvenir ?

*** Pour l'instant, je peux trouver, itérer, connecter et récupérer des données à partir du périphérique Joystick. C'est juste que je n'ai pas implémenté les appels bloquants.

...ICI est mon code expérimental/test... Veuillez ignorer les erreurs de syntaxe

#include <windows.h>
#include <dinput.h>
#include <stdio.h>
#include <iostream>
#include <sstream>
#include "joystick.h"

LPDIRECTINPUT8 di;
HRESULT hr;
LPDIRECTINPUTDEVICE8 joystick;
DIDEVCAPS capabilities;

BOOL CALLBACK
enumCallback(const DIDEVICEINSTANCE* instance, VOID* context)
{
    HRESULT hr;
    hr = di->CreateDevice(instance->guidInstance, &joystick, NULL);
    if (FAILED(hr)) {
        return DIENUM_CONTINUE;
    }
    return DIENUM_STOP;
}

int JoyStickProp()
{
    if (FAILED(hr = joystick->SetDataFormat(&c_dfDIJoystick2))) {
        return hr;
    }
    if (FAILED(hr = joystick->SetCooperativeLevel(NULL, DISCL_EXCLUSIVE |
        DISCL_FOREGROUND))) {
        return hr;
    }
    capabilities.dwSize = sizeof(DIDEVCAPS);
    if (FAILED(hr = joystick->GetCapabilities(&capabilities))) {
        return hr;
    }
}

HRESULT JoyStickPoll(DIJOYSTATE2 *js)
{
    HRESULT     hr;

    if (joystick == NULL) {
        return S_OK;
    }

    // Poll the device to read the current state
    hr = joystick->Poll();
    if (FAILED(hr)) {
        hr = joystick->Acquire();
        while (hr == DIERR_INPUTLOST) {
            hr = joystick->Acquire();
        }

        if ((hr == DIERR_INVALIDPARAM) || (hr == DIERR_NOTINITIALIZED)) {
            return E_FAIL;
        }

        // If another application has control of this device, return successfully.
        // We'll just have to wait our turn to use the joystick.
        if (hr == DIERR_OTHERAPPHASPRIO) {
            return S_OK;
        }
    }

    // Get the input's device state
    if (FAILED(hr = joystick->GetDeviceState(sizeof(DIJOYSTATE2), js))) {
        return hr; // The device should have been acquired during the Poll()
    }

    return S_OK;
}

int main()
{

    // Create a DirectInput device
    if (FAILED(hr = DirectInput8Create(GetModuleHandle(NULL), DIRECTINPUT_VERSION,
        IID_IDirectInput8, (VOID**)&di, NULL))) {
        return hr;
    }

    // Look for the first simple joystick we can find.
    if (FAILED(hr = di->EnumDevices(DI8DEVCLASS_GAMECTRL, enumCallback,
        NULL, DIEDFL_ATTACHEDONLY))) {
        return hr;
    }
    // Make sure we got a joystick
    if (joystick == NULL) {
        printf("Joystick not found.\n");
        return E_FAIL;
    }

    JoyStickProp();
    DIJOYSTATE2 diState;

    HANDLE ghWriteEvent;
    // Create joystick event stuff here
    ghWriteEvent = CreateEvent(
        NULL,               // default security attributes
        FALSE,               // manual-reset event
        FALSE,              // initial state is nonsignaled
        TEXT("WriteEvent")  // object name
        );

    //makesure we can read fromt the joystick before waiting for an event
    JoyStickPoll(&diState);
    printf("x axis %d", diState.lX);
    printf("y axis %d", diState.lY);
    JoyStickPoll(&diState);
    printf("x axis %d", diState.lX);
    printf("y axis %d", diState.lY);
    JoyStickPoll(&diState);
    printf("x axis %d", diState.lX);
    printf("y axis %d", diState.lY);
    JoyStickPoll(&diState);
    printf("x axis %d", diState.lX);
    printf("y axis %d", diState.lY);
    JoyStickPoll(&diState);
    printf("x axis %d", diState.lX);
    printf("y axis %d", diState.lY);
    JoyStickPoll(&diState);
    printf("x axis %d", diState.lX);
    printf("y axis %d", diState.lY);
joystick->SetEventNotification(ghWriteEvent);
    while (TRUE) {

        DWORD dwResult = WaitForSingleObject(
            ghWriteEvent, // event handle
            INFINITE);

        switch (dwResult) {
        case WAIT_OBJECT_0:
            // Event 1 has been set. If the event was created as
            // autoreset, it has also been reset. 
            int x = 0;
            //ProcessInputEvent1();
            break;
        }
    }
}

1voto

Roman R. Points 34579

La documentation MSDN pour IDirectInputDevice8::SetEventNotification() vous donne des extraits de code pertinents.

Vous devez appeler CreateEvent() et fournir les données retournées HANDLE en tant qu'argument pour SetEventNotification() . L'événement vous sera signalé lorsqu'un changement d'état se produira. Vous pouvez attendre l'événement, et une fois que vous avez la notification, vous obtenez les nouvelles données d'état à l'aide de IDirectInputDevice8::GetDeviceState() .

Toutes les normes Fonctions d'attente sont applicables à l'attente de la signalisation de l'événement. L'extrait de code suivant vous montre une façon de procéder, en utilisant la fonction MsgWaitForMultipleObjects() :

while (TRUE) { 

    dwResult = MsgWaitForMultipleObjects(2, ah, FALSE, INFINITE, QS_ALLINPUT); 
    switch (dwResult) { 
        case WAIT_OBJECT_0: 
            // Event 1 has been set. If the event was created as
            // autoreset, it has also been reset. 
            ProcessInputEvent1();
            break; 

Le site IDirectInputDevice8::Poll() est utilisée pour les appareils qui ne génèrent pas de notifications d'événements. Vous êtes censé les interroger parce qu'ils ne sont pas capables de fonctionner comme vous le souhaitez.

Certains joysticks et autres dispositifs de jeu, ou des objets particuliers sur ceux-ci, ne génèrent pas d'interruptions matérielles et ne renvoient pas de données ou ne signalent pas d'événements avant que vous n'appeliez la fonction IDirectInputDevice8::Poll méthode .

Vous n'interrogez qu'en cas de besoin lorsque les notifications ne fonctionnent pas pour un appareil. Le lien ci-dessus explique comment déterminer si l'interrogation est nécessaire.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X