简体   繁体   English

c ++ windows 中的操纵杆编程

[英]c++ programming for joystick in windows

i want to connect joystick to my c++ qt program in windows.I studied about programming with win32 api using the joystickapi library in microsoft guid for joystick program But I didn't understand exactly What should I do after checking the system compatibility?我想将操纵杆连接到我在 windows 中的 c++ qt 程序。我研究了使用 win32 api 使用microsoft guid 中的joystickapi 库进行操纵杆程序的编程但我不明白在检查系统兼容性后我应该怎么做?

Completion description:完成说明:

my code for system compatibility:我的系统兼容性代码:

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";

}

I want to track the movement of buttons and simulate it in software.How can I get joystick information (such as number of button and button on or off) from win32 api?我想跟踪按钮的移动并在软件中模拟它。如何从win32 api获取操纵杆信息(例如按钮数量和按钮开或关)?

According to Joysticks ,根据操纵杆的说法,

The multimedia joystick API has been superseded by DirectInput, which has more capabilities for today's input and force-feedback devices.多媒体游戏杆 API 已被 DirectInput 取代,后者为当今的输入和力反馈设备提供了更多功能。 For more information, see the DirectX documentation.有关详细信息,请参阅 DirectX 文档。

What you need is DirectInput , please start from Buffered Joystick Data .您需要的是DirectInput ,请从Buffered Joystick Data开始。

Each element in the DIDEVICEOBJECTDATA array represents a change in state for a single object on the joystick. DIDEVICEOBJECTDATA 数组中的每个元素代表操纵杆上单个对象的状态变化。 For instance, if the user presses button 0 and moves the stick diagonally, the array passed to IDirectInputDevice8::GetDeviceData (if it has at least three elements, and pdwInOut is at least 3) will have three elements filled in-an element for button 0 being pressed, an element for the change in the x-axis, and an element for the change in the y-axis-and the value of pdwInOut will be set to 3.例如,如果用户按下按钮 0 并沿对角线移动摇杆,则传递给 IDirectInputDevice8::GetDeviceData 的数组(如果它至少有三个元素,并且 pdwInOut 至少为 3)将在一个元素中填充三个元素用于按钮0 被按下,x 轴变化的元素和 y 轴变化的元素 - 和 pdwInOut 的值将设置为 3。

And Immediate Joystick Data ,即时操纵杆数据

To retrieve the current state of the joystick, call the IDirectInputDevice8::GetDeviceState method with a pointer to a DIJOYSTATE or a DIJOYSTATE2 structure, depending on whether the data format was set with c_dfDIJoystick or c_dfDIJoystick2.要检索操纵杆的当前状态,请使用指向 DIJOYSTATE 或 DIJOYSTATE2 结构的指针调用 IDirectInputDevice8::GetDeviceState 方法,具体取决于数据格式是使用 c_dfDIJoystick 还是 c_dfDIJoystick2 设置的。 (See Device Data Formats.) The joystick state returned in the structure includes the coordinates of the axes, the state of the buttons, and the state of the point-of-view controllers. (请参阅设备数据格式。)结构中返回的操纵杆状态包括轴的坐标、按钮的状态和视点控制器的状态。

I wrote a QJoystick lib in a form of a Qt module but it's not yet released.我以 Qt 模块的形式编写了一个 QJoystick 库,但尚未发布。

Here is a bit of code for Windows.这是一些适用于 Windows 的代码。

First, you need to initialize DirectInput:首先,您需要初始化 DirectInput:

#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)));
}

Second, setup callbacks:其次,设置回调:

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 is where you create a virtual device for your joystick: EnumJoysticksCallback是您为操纵杆创建虚拟设备的地方:

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;
}

And EnumObjectsCallback will be executed for every button or axis during the enumeration process:并且在枚举过程中,每个按钮或轴都会执行EnumObjectsCallback

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;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM