首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >windows下操纵杆的c++编程

windows下操纵杆的c++编程
EN

Stack Overflow用户
提问于 2020-10-12 08:25:09
回答 2查看 2.4K关注 0票数 1

我想把操纵杆连接到窗口中的c++ qt程序。我研究了如何使用win32 api编程,使用用于操纵杆程序的microsoft guid中的用于操纵杆程序的microsoft guid库,但是我不明白在检查系统兼容性之后应该做什么?

完成情况说明:

我的系统兼容性代码:

代码语言:javascript
复制
JOYINFO joyinfo;
UINT wNumDevs, wDeviceID;
BOOL bDev1Attached, bDev2Attached;
void joyCapablitis(){
    if((wNumDevs = joyGetNumDevs()) == 0)
        qDebug()<<"no driver available";
    bDev1Attached = joyGetPos(JOYSTICKID1,&joyinfo) != JOYERR_UNPLUGGED;
    bDev2Attached = wNumDevs == 2 && joyGetPos(JOYSTICKID2,&joyinfo) !=
            JOYERR_UNPLUGGED;
    if(bDev1Attached || bDev2Attached)   // decide which joystick to use
    {

        wDeviceID = bDev1Attached ? JOYSTICKID1 : JOYSTICKID2;

    }
    else
        qDebug()<<"no device available";

}

我想要跟踪按钮的运动,并在software.How中模拟它,我能从win32 api中获得操纵杆的信息(例如按钮的数量和按钮的开启或关闭)吗?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2020-10-12 12:27:24

我以Qt模块的形式编写了一个QJoystick库,但它尚未发布。

下面是Windows的一些代码。

首先,您需要初始化DirectInput:

代码语言:javascript
复制
#include "comdef.h"

#define SAFE_DELETE(p)  { if(p) { delete (p);     (p) = nullptr; }}
#define SAFE_RELEASE(p) { if(p) { (p)->Release(); (p) = nullptr; }}

#define AS(x, p) reinterpret_cast<x>(p)

BOOL CALLBACK EnumJoysticksCallback(const DIDEVICEINSTANCE*       deviceInstance, void* controller);
BOOL CALLBACK EnumObjectsCallback  (const DIDEVICEOBJECTINSTANCE* objectInstance, void* controller);

static LPDIRECTINPUT8 DirectInputPtr = nullptr;

HRESULT hr;

if (DirectInputPtr == nullptr)
{
    if (FAILED(hr = DirectInput8Create(GetModuleHandle(nullptr), DIRECTINPUT_VERSION, IID_IDirectInput8, AS(void**, &DirectInputPtr), nullptr)))
        qCritical("QJoystick failed to obtain direct input interface: %s", qPrintable(hrError(hr)));
}

其次,设置回调:

代码语言:javascript
复制
if (DirectInputPtr)
{
    if (FAILED(hr = DirectInputPtr->EnumDevices(DI8DEVCLASS_GAMECTRL, EnumJoysticksCallback, this, DIEDFL_ATTACHEDONLY)))
        qDebug("QJoystick EnumDevices failed");

    if (joystickPtr)
    {
        if (FAILED(hr = joystickPtr->SetDataFormat(&c_dfDIJoystick2)))
            qWarning("QJoystick: failed to set data format for id %d", deviceId);

        if (SUCCEEDED(hr = joystickPtr->EnumObjects(EnumObjectsCallback, this, DIDFT_ALL)))
        {
            DIDEVICEINSTANCE joystickinfo;
            joystickinfo.dwSize = sizeof(joystickinfo);

            if (FAILED(hr = joystickPtr->GetDeviceInfo(&joystickinfo)))
            {
                qCritical() << "QJoystick GetDeviceInfo failed:" << hrError(hr);
                SAFE_RELEASE(joystickPtr)
            }

            description = QString::fromWCharArray(joystickinfo.tszProductName);
            guid        = QString("%1").arg(joystickinfo.guidProduct.Data1, 8, 16, QLatin1Char('0'));
        }
        else
            qCritical("QJoystick: set callback on EnumObjects failed for %d", deviceId);
    }
}

EnumJoysticksCallback是您为您的操纵杆创建虚拟设备的地方:

代码语言:javascript
复制
BOOL CALLBACK EnumJoysticksCallback(const DIDEVICEINSTANCE* deviceInstance, void* pController)
{
    QJoystickPrivate* controller = AS(QJoystickPrivate*, pController);
    BOOL result = DIENUM_CONTINUE;

    if (controller->enumCounter == controller->deviceId)
    {
        HRESULT hr = DirectInputPtr->CreateDevice(deviceInstance->guidInstance, &(controller->joystickPtr), nullptr);

        if (SUCCEEDED(hr))
            result = DIENUM_STOP;
        else
            qWarning("QJoystick: CreateDevice failed %d", controller->deviceId);
    }
    else
        ++controller->enumCounter;

    return result;
}

在枚举过程中,将对每个按钮或轴执行EnumObjectsCallback

代码语言:javascript
复制
BOOL CALLBACK EnumObjectsCallback(const DIDEVICEOBJECTINSTANCE* objectInstance, void* pController)
{
    QJoystickPrivate* controller = AS(QJoystickPrivate*, pController);

    //Set the range for axis
    if (objectInstance->dwType & DIDFT_AXIS)
    {
        DIPROPRANGE diprg;

        diprg.diph.dwSize       = sizeof(DIPROPRANGE);
        diprg.diph.dwHeaderSize = sizeof(DIPROPHEADER);
        diprg.diph.dwHow        = DIPH_BYID;
        diprg.diph.dwObj        = objectInstance->dwType; // Specify the enumerated axis

        diprg.lMin = -1000;
        diprg.lMax = +1000;

        if (FAILED(controller->joystickPtr->SetProperty(DIPROP_RANGE, &diprg.diph)))
            return DIENUM_STOP;
    }

    if (objectInstance->guidType == GUID_XAxis  || objectInstance->guidType == GUID_YAxis  || objectInstance->guidType == GUID_ZAxis  ||
        objectInstance->guidType == GUID_RxAxis || objectInstance->guidType == GUID_RyAxis || objectInstance->guidType == GUID_RzAxis ||
        objectInstance->guidType == GUID_Slider)
    {
        // axis
    }
    else if (objectInstance->guidType == GUID_POV)
        // pov...
    else if (objectInstance->guidType == GUID_Button)
        // button...
    else if (objectInstance->guidType == GUID_Unknown)
        // unknown...

    return DIENUM_CONTINUE;
}
票数 1
EN

Stack Overflow用户

发布于 2020-10-12 09:36:38

操纵杆称,

多媒体操纵杆API已经被DirectInput所取代,它对当今的输入和力反馈设备有更多的功能。有关更多信息,请参见DirectX文档。

你需要的是DirectInput,请从缓冲Joystick数据开始。

DIDEVICEOBJECTDATA数组中的每个元素表示操纵杆上单个对象的状态变化。例如,如果用户按下按钮0并对角移动棒,则传递给IDirectInputDevice8::GetDeviceData的数组(如果它至少有三个元素,并且pdwInOut至少为3)将有三个元素填充--一个按钮0的元素,x轴中的更改元素,y轴中的更改元素--而pdwInOut的值将被设置为3。

即时Joystick数据

要检索操纵杆的当前状态,可以使用指向DIJOYSTATE或DIJOYSTATE2结构的指针调用IDirectInputDevice8::GetDeviceState方法,这取决于数据格式是用c_dfDIJoystick还是c_dfDIJoystick2设置的。(请参阅设备数据格式。)结构中返回的操纵杆状态包括轴的坐标、按钮的状态和视图控制器的状态。

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

https://stackoverflow.com/questions/64314175

复制
相关文章

相似问题

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