首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何在C++中使用微软的IDirectInputDevice8实现Joystick代码?

如何在C++中使用微软的IDirectInputDevice8实现Joystick代码?
EN

Stack Overflow用户
提问于 2017-05-12 21:56:36
回答 1查看 2.4K关注 0票数 3

我需要使用IDirectInputDevice8接口在直接输入设备上执行阻塞和非阻塞调用来轮询。

在linux中进行阻塞,我们使用选择 ex:

代码语言:javascript
复制
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 );
}

如何使用idirectinputdevice8 接口https://msdn.microsoft.com/en-us/library/windows/desktop/ee417816(v=vs.85).aspx做同样的事情?

即使设置了IDirectInputDevice8::SetEventNotification(),,每次也必须调用poll()来获取新数据,这是不可行的解决方案,因为它将导致cpu旋转。

我怎样才能做到这一点?

*目前,我可以找到、迭代、连接和从Joystick设备中获取数据。我只是没有执行阻塞调用。

...HERE是我的实验/测试代码..。请忽略语法错误

代码语言:javascript
复制
#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;
        }
    }
}
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2017-05-12 22:52:44

IDirectInputDevice8::SetEventNotification()的MSDN文档为您提供了相关的代码片段。

您需要调用CreateEvent()并提供返回的HANDLE作为SetEventNotification()的参数。当发生状态更改时,将向您发出此事件的信号。您可以等待事件,然后一旦收到通知,就可以使用IDirectInputDevice8::GetDeviceState()获得新的状态数据。

所有标准的等待函数都适用于等待事件的信号。下面的代码片段显示了一种使用MsgWaitForMultipleObjects()的方法:

代码语言:javascript
复制
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; 

IDirectInputDevice8::Poll()方法用于不生成事件通知的设备。你应该投票他们,因为他们没有能力按照你想要的方式操作。

一些操纵杆和其他游戏设备,或它们上的特定对象,方法

只有在需要时,当通知对设备不起作用时,才进行轮询。上面的链接解释了如何识别轮询是否必要。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/43947007

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档