windows 中操纵杆的 C++ 编程
c++ programming for joystick in windows
我想在 windows.I 中将游戏杆连接到我的 c++ qt 程序 在 microsoft guid for joystick program 中使用游戏杆 api 库研究了 win32 编程 api 但我没有不太明白 检查系统兼容性后我该怎么办?
完成说明:
我的系统兼容性代码:
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?
根据Joysticks,
The multimedia joystick API has been superseded by DirectInput, which
has more capabilities for today's input and force-feedback devices.
For more information, see the DirectX documentation.
你需要的是DirectInput, please start from Buffered Joystick Data.
Each element in the DIDEVICEOBJECTDATA array represents a change in
state for a single object on the joystick. 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.
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. (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.
我以 Qt 模块的形式编写了一个 QJoystick 库,但尚未发布。
这是 Windows 的一些代码。
首先,您需要初始化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)));
}
二、设置回调:
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
是您为操纵杆创建虚拟设备的地方:
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
将在枚举过程中对每个按钮或轴执行:
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;
}
我想在 windows.I 中将游戏杆连接到我的 c++ qt 程序 在 microsoft guid for joystick program 中使用游戏杆 api 库研究了 win32 编程 api 但我没有不太明白 检查系统兼容性后我该怎么办?
完成说明:
我的系统兼容性代码:
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?
根据Joysticks,
The multimedia joystick API has been superseded by DirectInput, which has more capabilities for today's input and force-feedback devices. For more information, see the DirectX documentation.
你需要的是DirectInput, please start from Buffered Joystick Data.
Each element in the DIDEVICEOBJECTDATA array represents a change in state for a single object on the joystick. 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.
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. (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.
我以 Qt 模块的形式编写了一个 QJoystick 库,但尚未发布。
这是 Windows 的一些代码。
首先,您需要初始化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)));
}
二、设置回调:
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
是您为操纵杆创建虚拟设备的地方:
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
将在枚举过程中对每个按钮或轴执行:
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;
}