功能全面地封装了XInput的输入,
1. 普通按钮按下, 按住, 弹起状态检查,
2. 摇杆4个方向的按下, 按住, 弹起检查
3. 按键状态变化检测并且记录按下触发时间, 按住保持时间, 方便用来完全自定义的输入功能
4. 多手柄输入合并
5. 支持检索 西瓜键(Guide按键)
CXInputHelper.h
#pragma once
//
// @brief: XInput 输入事件封装辅助类
// @copyright: Copyright 2024 FlameCyclone
// @license: MIT
// @birth: created by FlameCyclone on 2024-09-07
// @version: V1.0.0
// @revision: last revised by FlameCyclone on 2024-09-11
//
#include <windows.h>
#include <xinput.h>
#include <tchar.h>
#include <stdint.h>
#include <thread>
#include <functional>
#include <string>
#include <map>
#pragma comment(lib, "xinput.lib")
// 禁用无名结构体/联合体警告 Disable warning C4201:nameless struct/union
#if _MSC_VER >= 1200
#pragma warning(push)
#endif
#pragma warning(disable : 4201)
// 禁用警告: 未引用的形参
#pragma warning(disable : 4100)
#define PI (3.141592653589793f)
#define ANGLE_RANGE (22.5f)
#ifdef _UNICODE
using _tstring = std::wstring;
#else
using _tstring = std::string;
#endif
//
// 游戏手柄按钮常量
//
//#define XINPUT_GAMEPAD_DPAD_UP 0x0001
//#define XINPUT_GAMEPAD_DPAD_DOWN 0x0002
//#define XINPUT_GAMEPAD_DPAD_LEFT 0x0004
//#define XINPUT_GAMEPAD_DPAD_RIGHT 0x0008
//#define XINPUT_GAMEPAD_START 0x0010
//#define XINPUT_GAMEPAD_BACK 0x0020
//#define XINPUT_GAMEPAD_LEFT_THUMB 0x0040
//#define XINPUT_GAMEPAD_RIGHT_THUMB 0x0080
//#define XINPUT_GAMEPAD_LEFT_SHOULDER 0x0100
//#define XINPUT_GAMEPAD_RIGHT_SHOULDER 0x0200
#define XINPUT_GAMEPAD_GUIDE (0x00000400)
#define XINPUT_GAMEPAD_SHARE (0x00000800)
//#define XINPUT_GAMEPAD_A 0x1000
//#define XINPUT_GAMEPAD_B 0x2000
//#define XINPUT_GAMEPAD_X 0x4000
//#define XINPUT_GAMEPAD_Y 0x8000
#define XINPUT_GAMEPAD_LEFT_TRIGGER (0x00010000)
#define XINPUT_GAMEPAD_RIGHT_TRIGGER (0x00020000)
#define XINPUT_GAMEPAD_LEFT_STICK (0x00040000)
#define XINPUT_GAMEPAD_RIGHT_STICK (0x00080000)
// 按键枚举
enum eGamepadButton
{
eGamepad_None = 0, // 无
eGamepad_Dpad_Up = 1 << 0x00, // 十字键 上 Up
eGamepad_Dpad_Down = 1 << 0x01, // 十字键 下 Down
eGamepad_Dpad_Left = 1 << 0x02, // 十字键 左 Left
eGamepad_Dpad_Right = 1 << 0x03, // 十字键 右 Right
eGamepad_Start = 1 << 0x04, // 菜单键(开始键) Start
eGamepad_Back = 1 << 0x05, // 返回键(选择键) Back
eGamepad_LSB = 1 << 0x06, // 左摇杆键 Left Stick Button
eGamepad_RSB = 1 << 0x07, // 右摇杆键 Right Stick Button
eGamepad_LB = 1 << 0x08, // 左肩键 Left Bumper
eGamepad_RB = 1 << 0x09, // 右肩键 Right Bumper
eGamepad_Guide = 1 << 0x0A, // 西瓜键(导航键) Guide
eGamepad_Share = 1 << 0x0B, // 分享键(假设, 未验证) Share
eGamepad_A = 1 << 0x0C, // A
eGamepad_B = 1 << 0x0D, // B
eGamepad_X = 1 << 0x0E, // X
eGamepad_Y = 1 << 0x0F, // Y
eGamepad_LT = 1 << 0x10, // 左扳机 Left Trigger
eGamepad_RT = 1 << 0x11, // 右扳机 Right Trigger
eGamepad_LS = 1 << 0x12, // 左摇杆 Left Stick
eGamepad_RS = 1 << 0x13, // 右摇杆 Right Stick
};
// 按键状态位
typedef union _GAMEPAD_BUTTON_STATE
{
uint32_t Button; // 按钮状态值
struct
{
// 标准 XBOX 控制器按钮
uint16_t Dpad_Up : 1; // 十字键 上 Up
uint16_t Dpad_Down : 1; // 十字键 下 Down
uint16_t Dpad_Left : 1; // 十字键 左 Left
uint16_t Dpad_Right : 1; // 十字键 右 Right
uint16_t Start : 1; // 菜单键(开始键) Start
uint16_t Back : 1; // 返回键(选择键) Back
uint16_t LSB : 1; // 左摇杆键 Left Stick Button
uint16_t RSB : 1; // 右摇杆键 Right Stick Button
uint16_t LB : 1; // 左肩键 Left Bumper
uint16_t RB : 1; // 右肩键 Right Bumper
uint16_t Guide : 1; // 西瓜键(导航键) Guide
uint16_t Share : 1; // 分享键(假设, 未验证) Share
uint16_t A : 1; // A
uint16_t B : 1; // B
uint16_t X : 1; // X
uint16_t Y : 1; // Y
// 根据摇杆方向假设的摇杆方向键
uint16_t LS_Up : 1; // 左摇杆 上
uint16_t LS_Down : 1; // 左摇杆 下
uint16_t LS_Left : 1; // 左摇杆 左
uint16_t LS_Right : 1; // 左摇杆 右
uint16_t RS_Up : 1; // 右摇杆 上
uint16_t RS_Down : 1; // 右摇杆 下
uint16_t RS_Left : 1; // 右摇杆 左
uint16_t RS_Right : 1; // 右摇杆 右
// 根据扳机假设的按键
uint16_t LT : 1; // 左扳机 Left Trigger
uint16_t RT : 1; // 右扳机 Right Trigger
// 根据摇杆假设的按键
uint16_t LS : 1; // 左摇杆 Left Stick
uint16_t RS : 1; // 右摇杆 Right Stick
uint16_t Reserved : 4; // 保留位
} DUMMYSTRUCTNAME;
}GAMEPAD_BUTTON_STATE;
// 按钮事件
typedef struct _GAMEPAD_BUTTON_EVENT
{
uint32_t uData; // 事件附加数据
uint32_t uTime; // 触发时间
uint32_t uDuration; // 持续时长
union
{
uint8_t Event; // 事件值
struct
{
uint8_t Down : 1; // 按下
uint8_t Hold : 1; // 按住
uint8_t Up : 1; // 弹起
} DUMMYSTRUCTNAME;
} DUMMYUNIONNAME;
}GAMEPAD_BUTTON_EVENT;
// 摇杆轴状态
typedef union _GAMEPAD_AXIS_STATE
{
uint8_t State; // 状态值
struct
{
uint8_t Up : 1; // 上
uint8_t Down : 1; // 下
uint8_t Left : 1; // 左
uint8_t Right : 1; // 右
} DUMMYSTRUCTNAME;
}GAMEPAD_AXIS_STATE;
// 摇杆轴事件
typedef struct _GAMEPAD_AXIS_EVENT
{
GAMEPAD_BUTTON_EVENT Up; // 轴方向事件上
GAMEPAD_BUTTON_EVENT Down; // 轴方向事件下
GAMEPAD_BUTTON_EVENT Left; // 轴方向事件左
GAMEPAD_BUTTON_EVENT Right; // 轴方向事件右
GAMEPAD_AXIS_STATE curAxisState; // 当前轴方向状态
GAMEPAD_AXIS_STATE lastAxisState; // 上次轴方向状态
}GAMEPAD_AXIS_EVENT;
// 输入事件状态
typedef struct _GAMEPAD_INPUT_EVENT
{
uint32_t uIndex; // 手柄索引
eGamepadButton eButton; // 当前按钮枚举
XINPUT_STATE xinputState; // 当前手柄输入状态
GAMEPAD_BUTTON_EVENT curButtonEvent; // 当前按键事件
GAMEPAD_AXIS_EVENT curAxisEvent; // 当前轴事件
GAMEPAD_BUTTON_STATE curButtonState; // 当前按键位状态
GAMEPAD_BUTTON_STATE lastButtonState; // 上次按键位状态
int16_t sAxisX; // 当前摇杆X值
int16_t sAxisY; // 当前摇杆Y值
uint8_t bTrigger; // 扳机数据
uint8_t fRight; // 右 扳机/肩键/摇杆标志
_GAMEPAD_INPUT_EVENT()
{
memset(this, 0, sizeof(*this));
}
}GAMEPAD_INPUT_EVENT;
// 输入事件回调信息
class CXInputHelper;
typedef void (CXInputHelper::*pInputEventFn)(GAMEPAD_INPUT_EVENT& event);
typedef struct _INPUT_EVENT_INFO
{
pInputEventFn cbEvent; // 输入事件变化回调函数
GAMEPAD_INPUT_EVENT eventState; // 输入事件变化状态
_INPUT_EVENT_INFO(pInputEventFn cb)
:
cbEvent(cb)
{
}
}GAMEPAD_EVENT_CB_INFO;
class CXInputHelper
{
public:
CXInputHelper();
virtual ~CXInputHelper();
// 打印文本
static void PrintText(LPCTSTR pFormat, ...);
// 初始化
bool Initialize();
// 反初始化
void Uninitialize();
// 打印状态信息
virtual void PrintState(
const GAMEPAD_INPUT_EVENT& event // 按钮事件
);
// 设置数据轮询时间
void SetInterval(
int millisecond = 10 // 数据轮询时间(毫秒)
);
// 设置轴触发阈值
void SetAxisThreshold(
int16_t nLeft = 4096, // 左摇杆触发阈值(死区)
int16_t nRight = 4096 // 右摇杆触发阈值(死区)
);
// 设置轴阈值请求回调
void SetAxisThresholdQuery(
std::function<void(
int16_t& nLeft, // 左摇杆触发阈值(死区)
int16_t& nRight // 右摇杆触发阈值(死区)
)> cb
);
// 设置检测每个控制器输入数据回调
void SetRawStateCallback(
std::function<void(
uint32_t dwIndex, // 控制器索引(有效值: 0 - 3)
const XINPUT_GAMEPAD& xGamepad // 控制器数据
)> cb
);
// 设置合并多个控制器输入数据回调
void SetMergeStateCallback(
std::function<void(
const XINPUT_GAMEPAD& xGamepad // 控制器数据
)> cb
);
// 设置检测每个控制器输入状态变化回调
void SetRawEventCallback(
std::function<void(
GAMEPAD_INPUT_EVENT& event // 回调事件信息
)> cb
);
// 设置合并多个控制器输入状态变化回调
void SetMergeEventCallback(
std::function<void(
GAMEPAD_INPUT_EVENT& event // 回调事件信息
)> cb
);
// 输入变化
virtual void OnEventDpadUp(GAMEPAD_INPUT_EVENT& event) {};
virtual void OnEventDpadDown(GAMEPAD_INPUT_EVENT& event) {};
virtual void OnEventDpadLeft(GAMEPAD_INPUT_EVENT& event) {};
virtual void OnEventDpadRight(GAMEPAD_INPUT_EVENT& event) {};
virtual void OnEventBack(GAMEPAD_INPUT_EVENT& event) {};
virtual void OnEventStart(GAMEPAD_INPUT_EVENT& event) {};
virtual void OnEventGuide(GAMEPAD_INPUT_EVENT& event) {};
virtual void OnEventShare(GAMEPAD_INPUT_EVENT& event) {};
virtual void OnEventA(GAMEPAD_INPUT_EVENT& event) {};
virtual void OnEventB(GAMEPAD_INPUT_EVENT& event) {};
virtual void OnEventX(GAMEPAD_INPUT_EVENT& event) {};
virtual void OnEventY(GAMEPAD_INPUT_EVENT& event) {};
virtual void OnEventLB(GAMEPAD_INPUT_EVENT& event) {};
virtual void OnEventRB(GAMEPAD_INPUT_EVENT& event) {};
virtual void OnEventLT(GAMEPAD_INPUT_EVENT& event) {};
virtual void OnEventRT(GAMEPAD_INPUT_EVENT& event) {};
virtual void OnEventLS(GAMEPAD_INPUT_EVENT& event) {};
virtual void OnEventRS(GAMEPAD_INPUT_EVENT& event) {};
virtual void OnEventLSB(GAMEPAD_INPUT_EVENT& event) {};
virtual void OnEventRSB(GAMEPAD_INPUT_EVENT& event) {};
// 合并输入变化
virtual void OnMergeEventDpadUp(GAMEPAD_INPUT_EVENT& event){};
virtual void OnMergeEventDpadDown(GAMEPAD_INPUT_EVENT& event) {};
virtual void OnMergeEventDpadLeft(GAMEPAD_INPUT_EVENT& event) {};
virtual void OnMergeEventDpadRight(GAMEPAD_INPUT_EVENT& event) {};
virtual void OnMergeEventBack(GAMEPAD_INPUT_EVENT& event) {};
virtual void OnMergeEventStart(GAMEPAD_INPUT_EVENT& event) {};
virtual void OnMergeEventGuide(GAMEPAD_INPUT_EVENT& event) {};
virtual void OnMergeEventShare(GAMEPAD_INPUT_EVENT& event) {};
virtual void OnMergeEventA(GAMEPAD_INPUT_EVENT& event) {};
virtual void OnMergeEventB(GAMEPAD_INPUT_EVENT& event) {};
virtual void OnMergeEventX(GAMEPAD_INPUT_EVENT& event) {};
virtual void OnMergeEventY(GAMEPAD_INPUT_EVENT& event) {};
virtual void OnMergeEventLB(GAMEPAD_INPUT_EVENT& event) {};
virtual void OnMergeEventRB(GAMEPAD_INPUT_EVENT& event) {};
virtual void OnMergeEventLT(GAMEPAD_INPUT_EVENT& event) {};
virtual void OnMergeEventRT(GAMEPAD_INPUT_EVENT& event) {};
virtual void OnMergeEventLS(GAMEPAD_INPUT_EVENT& event) {};
virtual void OnMergeEventRS(GAMEPAD_INPUT_EVENT& event) {};
virtual void OnMergeEventLSB(GAMEPAD_INPUT_EVENT& event) {};
virtual void OnMergeEventRSB(GAMEPAD_INPUT_EVENT& event) {};
private:
// 任务循环
void _GamepadLoop();
// 睡眠间隔
void _Sleep(int millisecond);
// 更新轴事件
void _UpdateAxisEvent(GAMEPAD_BUTTON_EVENT& event, bool fCur, bool fLast);
// 解析轴状态
GAMEPAD_AXIS_STATE _ParseAxisState(int16_t sAxisX, int16_t sAxisY, int16_t nThreshold);
// 更新按钮状态
void _UpdateButtonState(GAMEPAD_INPUT_EVENT& event, const XINPUT_GAMEPAD& cur);
// 更新按钮变化事件
void _UpdateButtonEvent(GAMEPAD_INPUT_EVENT& event, const XINPUT_GAMEPAD& cur);
// 状态变化输入处理
void _InputEventProcess(uint32_t dwIndex);
// 混合输入处理
void _InputMergeProcess();
// 混合输入变化处理
void _InputMergeEventProcess();
private:
std::function<void(uint32_t dwIndex, const XINPUT_GAMEPAD& xGamepad)> m_cbRawState; // 检测每个控制器输入数据回调
std::function<void(const XINPUT_GAMEPAD& xGamepad)> m_cbMergeState; // 合并多个控制器输入数据回调
std::function<void(GAMEPAD_INPUT_EVENT& event)> m_cbRawEvent; // 检测每个控制器输入事件回调
std::function<void(GAMEPAD_INPUT_EVENT& event)> m_cbMergeEvent; // 合并多个控制器输入事件回调
std::function<void(int16_t& nLeft, int16_t& nRight)> m_cbAxisQuery; // 摇杆轴阈值请求回调
std::map<eGamepadButton, GAMEPAD_EVENT_CB_INFO> m_buttonEvents[XUSER_MAX_COUNT]; // 按钮输入事件信息映射
std::map<eGamepadButton, GAMEPAD_EVENT_CB_INFO> m_mergeEvents; // 合并输入事件信息映射
std::thread m_gamepadTask; // 控制器状态检测任务线程
int32_t m_DataInterval; // 采集间隔时间
int16_t m_LeftAxisThreshold; // 左摇杆触发阈值
int16_t m_RightAxisThreshold; // 右摇杆触发阈值
bool m_fQuit; // 退出标志
public:
XINPUT_STATE m_CurXInputStateIndex[XUSER_MAX_COUNT]; // 当前控制器输入状态
XINPUT_STATE m_CurXInputStateMerge; // 当前全部控制器混合输入状态
GAMEPAD_BUTTON_STATE m_CurButtonStateIndex[XUSER_MAX_COUNT]; // 当前按钮掩码状态
GAMEPAD_BUTTON_STATE m_CurButtonStateMerge; // 当前合并后按钮掩码状态
};
CXInputHelper.cpp
#include "CXInputHelper.h"
#include <math.h>
#pragma comment(lib, "WinMM.Lib")
void CXInputHelper::_Sleep(int millisecond)
{
//timeBeginPeriod(1);
do
{
const int span = 1;
if (millisecond < span)
{
std::this_thread::sleep_for(std::chrono::milliseconds(millisecond));
return;
}
clock_t tmBegin = clock();
while (true)
{
if (::clock() - tmBegin > millisecond)
{
break;
}
if (m_fQuit)
{
break;
}
std::this_thread::sleep_for(std::chrono::milliseconds(span));
}
} while (false);
//timeEndPeriod(1);
}
void CXInputHelper::PrintText(LPCTSTR pFormat, ...)
{
size_t nCchCount = MAX_PATH;
_tstring strResult(nCchCount, 0);
va_list args;
va_start(args, pFormat);
do
{
//格式化输出字符串
int nSize = _vsntprintf_s(&strResult[0], nCchCount, _TRUNCATE, pFormat, args);
if (-1 != nSize)
{
HANDLE console = ::GetStdHandle(STD_OUTPUT_HANDLE);
::WriteConsole(console, strResult.c_str(), nSize, NULL, NULL);
break;
}
//缓冲大小超限终止
if (nCchCount >= INT32_MAX)
{
break;
}
//重新分配缓冲
nCchCount *= 2;
strResult.resize(nCchCount);
} while (true);
va_end(args);
}
CXInputHelper::CXInputHelper()
:
m_fQuit(false),
m_LeftAxisThreshold(0),
m_RightAxisThreshold(0),
m_DataInterval(10)
{
memset(&m_CurXInputStateIndex, 0, sizeof(m_CurXInputStateIndex));
memset(&m_CurXInputStateMerge, 0, sizeof(m_CurXInputStateMerge));
memset(&m_CurButtonStateIndex, 0, sizeof(m_CurButtonStateIndex));
memset(&m_CurButtonStateMerge, 0, sizeof(m_CurButtonStateMerge));
}
CXInputHelper::~CXInputHelper()
{
Uninitialize();
}
bool CXInputHelper::Initialize()
{
Uninitialize();
m_gamepadTask = std::move(std::thread([this]() {
_GamepadLoop();
}));
return true;
}
void CXInputHelper::Uninitialize()
{
if (m_gamepadTask.joinable())
{
m_fQuit = true;
m_gamepadTask.join();
}
m_fQuit = false;
}
void CXInputHelper::SetInterval(
int millisecond
)
{
m_DataInterval = millisecond;
}
void CXInputHelper::SetAxisThreshold(
int16_t nLeft/* = 4096*/,
int16_t nRight/* = 4096*/
)
{
m_LeftAxisThreshold = nLeft;
m_RightAxisThreshold = nRight;
}
void CXInputHelper::SetAxisThresholdQuery(
std::function<void(
int16_t& nLeft,
int16_t& nRight
)> cb
)
{
m_cbAxisQuery = cb;
}
void CXInputHelper::SetRawStateCallback(
std::function<void(
uint32_t uIndex,
const XINPUT_GAMEPAD& xGamepad
)> cb
)
{
m_cbRawState = cb;
}
void CXInputHelper::SetMergeStateCallback(
std::function<void(
const XINPUT_GAMEPAD& xGamepad
)> cb
)
{
m_cbMergeState = cb;
}
void CXInputHelper::SetRawEventCallback(
std::function<void(
GAMEPAD_INPUT_EVENT& event
)> cb
)
{
m_cbRawEvent = cb;
}
void CXInputHelper::SetMergeEventCallback(
std::function<void(
GAMEPAD_INPUT_EVENT& event
)> cb
)
{
m_cbMergeEvent = cb;
}
void CXInputHelper::PrintState(
const GAMEPAD_INPUT_EVENT& event
)
{
PrintText(_T("Mask: %08X bRight: %d Trigger: %3d Axis: %6d,%6d Data: %d Buttons: %.8X Duration: %6d L: %d U: %d R: %d D: %d\r\n"),
event.eButton,
event.fRight, event.bTrigger,
event.sAxisX, event.sAxisY,
event.curButtonEvent.Event,
event.curButtonState.Button,
event.curButtonEvent.uDuration,
event.curAxisEvent.Left.Event,
event.curAxisEvent.Up.Event,
event.curAxisEvent.Right.Event,
event.curAxisEvent.Down.Event
);
}
void CXInputHelper::_GamepadLoop()
{
m_buttonEvents[0] = {
{eGamepadButton::eGamepad_Dpad_Up , GAMEPAD_EVENT_CB_INFO(&CXInputHelper::OnEventDpadUp) },
{eGamepadButton::eGamepad_Dpad_Down , GAMEPAD_EVENT_CB_INFO(&CXInputHelper::OnEventDpadDown) },
{eGamepadButton::eGamepad_Dpad_Left , GAMEPAD_EVENT_CB_INFO(&CXInputHelper::OnEventDpadLeft) },
{eGamepadButton::eGamepad_Dpad_Right , GAMEPAD_EVENT_CB_INFO(&CXInputHelper::OnEventDpadRight) },
{eGamepadButton::eGamepad_Start , GAMEPAD_EVENT_CB_INFO(&CXInputHelper::OnEventStart) },
{eGamepadButton::eGamepad_Back , GAMEPAD_EVENT_CB_INFO(&CXInputHelper::OnEventBack) },
{eGamepadButton::eGamepad_LSB , GAMEPAD_EVENT_CB_INFO(&CXInputHelper::OnEventLSB) },
{eGamepadButton::eGamepad_RSB , GAMEPAD_EVENT_CB_INFO(&CXInputHelper::OnEventRSB) },
{eGamepadButton::eGamepad_LB , GAMEPAD_EVENT_CB_INFO(&CXInputHelper::OnEventLB) },
{eGamepadButton::eGamepad_RB , GAMEPAD_EVENT_CB_INFO(&CXInputHelper::OnEventRB) },
{eGamepadButton::eGamepad_Guide , GAMEPAD_EVENT_CB_INFO(&CXInputHelper::OnEventGuide) },
{eGamepadButton::eGamepad_Share , GAMEPAD_EVENT_CB_INFO(&CXInputHelper::OnEventShare) },
{eGamepadButton::eGamepad_A , GAMEPAD_EVENT_CB_INFO(&CXInputHelper::OnEventA) },
{eGamepadButton::eGamepad_B , GAMEPAD_EVENT_CB_INFO(&CXInputHelper::OnEventB) },
{eGamepadButton::eGamepad_X , GAMEPAD_EVENT_CB_INFO(&CXInputHelper::OnEventX) },
{eGamepadButton::eGamepad_Y , GAMEPAD_EVENT_CB_INFO(&CXInputHelper::OnEventY) },
{eGamepadButton::eGamepad_LT , GAMEPAD_EVENT_CB_INFO(&CXInputHelper::OnEventLT) },
{eGamepadButton::eGamepad_RT , GAMEPAD_EVENT_CB_INFO(&CXInputHelper::OnEventRT) },
{eGamepadButton::eGamepad_LS , GAMEPAD_EVENT_CB_INFO(&CXInputHelper::OnEventLS) },
{eGamepadButton::eGamepad_RS , GAMEPAD_EVENT_CB_INFO(&CXInputHelper::OnEventRS) }
};
m_buttonEvents[1] = m_buttonEvents[0];
m_buttonEvents[2] = m_buttonEvents[0];
m_buttonEvents[3] = m_buttonEvents[0];
m_mergeEvents = {
{eGamepadButton::eGamepad_Dpad_Up , GAMEPAD_EVENT_CB_INFO(&CXInputHelper::OnMergeEventDpadUp) },
{eGamepadButton::eGamepad_Dpad_Down , GAMEPAD_EVENT_CB_INFO(&CXInputHelper::OnMergeEventDpadDown) },
{eGamepadButton::eGamepad_Dpad_Left , GAMEPAD_EVENT_CB_INFO(&CXInputHelper::OnMergeEventDpadLeft) },
{eGamepadButton::eGamepad_Dpad_Right , GAMEPAD_EVENT_CB_INFO(&CXInputHelper::OnMergeEventDpadRight) },
{eGamepadButton::eGamepad_Start , GAMEPAD_EVENT_CB_INFO(&CXInputHelper::OnMergeEventStart) },
{eGamepadButton::eGamepad_Back , GAMEPAD_EVENT_CB_INFO(&CXInputHelper::OnMergeEventBack) },
{eGamepadButton::eGamepad_LSB , GAMEPAD_EVENT_CB_INFO(&CXInputHelper::OnMergeEventLSB) },
{eGamepadButton::eGamepad_RSB , GAMEPAD_EVENT_CB_INFO(&CXInputHelper::OnMergeEventRSB) },
{eGamepadButton::eGamepad_LB , GAMEPAD_EVENT_CB_INFO(&CXInputHelper::OnMergeEventLB) },
{eGamepadButton::eGamepad_RB , GAMEPAD_EVENT_CB_INFO(&CXInputHelper::OnMergeEventRB) },
{eGamepadButton::eGamepad_Guide , GAMEPAD_EVENT_CB_INFO(&CXInputHelper::OnMergeEventGuide) },
{eGamepadButton::eGamepad_Share , GAMEPAD_EVENT_CB_INFO(&CXInputHelper::OnMergeEventShare) },
{eGamepadButton::eGamepad_A , GAMEPAD_EVENT_CB_INFO(&CXInputHelper::OnMergeEventA) },
{eGamepadButton::eGamepad_B , GAMEPAD_EVENT_CB_INFO(&CXInputHelper::OnMergeEventB) },
{eGamepadButton::eGamepad_X , GAMEPAD_EVENT_CB_INFO(&CXInputHelper::OnMergeEventX) },
{eGamepadButton::eGamepad_Y , GAMEPAD_EVENT_CB_INFO(&CXInputHelper::OnMergeEventY) },
{eGamepadButton::eGamepad_LT , GAMEPAD_EVENT_CB_INFO(&CXInputHelper::OnMergeEventLT) },
{eGamepadButton::eGamepad_RT , GAMEPAD_EVENT_CB_INFO(&CXInputHelper::OnMergeEventRT) },
{eGamepadButton::eGamepad_LS , GAMEPAD_EVENT_CB_INFO(&CXInputHelper::OnMergeEventLS) },
{eGamepadButton::eGamepad_RS , GAMEPAD_EVENT_CB_INFO(&CXInputHelper::OnMergeEventRS) }
};
// 加载 控制器状态检测 函数
HMODULE hModule = LoadLibrary(_T("XInput1_4.dll"));
if (NULL == hModule) hModule = LoadLibrary(_T("xinput1_3.dll"));
if (NULL == hModule) return;
typedef int(__stdcall* _XInputGetStateEx)(uint32_t dwUserIndex, XINPUT_STATE* pState);
_XInputGetStateEx XInputGetStateEx = (_XInputGetStateEx)::GetProcAddress(hModule, (LPCSTR)100);
if (nullptr == XInputGetStateEx)
{
XInputGetStateEx = (_XInputGetStateEx)::GetProcAddress(hModule, "XInputGetState");
}
int16_t nLeftAxisThreshold = m_LeftAxisThreshold;
int16_t nRightAxisThreshold = m_RightAxisThreshold;
clock_t tmCount = ::clock();
while (!m_fQuit && XInputGetStateEx)
{
// 遍历控制器输入
for (uint32_t i = 0; i < XUSER_MAX_COUNT; ++i)
{
XINPUT_STATE xTmpState = { 0 };
uint32_t dwResult = XInputGetStateEx(i, &xTmpState);
nLeftAxisThreshold = m_LeftAxisThreshold;
nRightAxisThreshold = m_RightAxisThreshold;
// 轴触发限定值查询
if (m_cbAxisQuery)
{
m_cbAxisQuery(nLeftAxisThreshold, nRightAxisThreshold);
}
// 摇杆触发值限定
if (abs(xTmpState.Gamepad.sThumbLX) < nLeftAxisThreshold) xTmpState.Gamepad.sThumbLX = 0;
if (abs(xTmpState.Gamepad.sThumbLY) < nLeftAxisThreshold) xTmpState.Gamepad.sThumbLY = 0;
if (abs(xTmpState.Gamepad.sThumbRX) < nRightAxisThreshold) xTmpState.Gamepad.sThumbRX = 0;
if (abs(xTmpState.Gamepad.sThumbRY) < nRightAxisThreshold) xTmpState.Gamepad.sThumbRY = 0;
m_CurXInputStateIndex[i] = xTmpState;
// 原始数据回调
if (m_cbRawState)
{
m_cbRawState(i, xTmpState.Gamepad);
}
// 未连接控制器
if (ERROR_DEVICE_NOT_CONNECTED == dwResult)
{
continue;
}
// 单控制器输入变化处理
_InputEventProcess(i);
}
// 混合输入处理
_InputMergeProcess();
// 混合输入变化处理
_InputMergeEventProcess();
// 输入轮询间隔
while (clock() - tmCount < m_DataInterval)
{
_Sleep(1);
}
tmCount = clock();
}
if (hModule)
{
::FreeLibrary(hModule);
}
}
GAMEPAD_AXIS_STATE CXInputHelper::_ParseAxisState(int16_t sAxisX, int16_t sAxisY, int16_t nThreshold)
{
GAMEPAD_AXIS_STATE axisResult = { 0 };
double fCurAngle = atan2(sAxisY, sAxisX) * 180.0f / PI;
if (fCurAngle < 0)
{
fCurAngle = 360.0f + fCurAngle;
}
// 上
if (sAxisY > nThreshold)
{
if (fCurAngle >= (90.0f - ANGLE_RANGE) && fCurAngle <= (90.0f + ANGLE_RANGE))
{
axisResult.Up = 1;
}
}
// 下
if (sAxisY < -nThreshold)
{
if (fCurAngle >= (270.0f - ANGLE_RANGE) && fCurAngle <= (270.0f + ANGLE_RANGE))
{
axisResult.Down = 1;
}
}
// 左
if (sAxisX < -nThreshold)
{
if (fCurAngle >= (180.0f - ANGLE_RANGE) || fCurAngle <= (180.0f + ANGLE_RANGE))
{
axisResult.Left = 1;
}
}
// 右
if (sAxisX > nThreshold)
{
if (fCurAngle >= (360.0f - ANGLE_RANGE) || fCurAngle <= (0.0f + ANGLE_RANGE))
{
axisResult.Right = 1;
}
}
// 左上
if (sAxisX < -nThreshold && sAxisY > nThreshold)
{
if (fCurAngle > (90.0f + 45.0f - ANGLE_RANGE) && fCurAngle < (90.0f + 45.0f + ANGLE_RANGE))
{
axisResult.Left = 1;
axisResult.Up = 1;
}
}
// 右上
if (sAxisX > nThreshold && sAxisY > nThreshold)
{
if (fCurAngle > (90.0f - 45.0f - ANGLE_RANGE) && fCurAngle < (90.0f - 45.0f + ANGLE_RANGE))
{
axisResult.Right = 1;
axisResult.Up = 1;
}
}
// 左下
if (sAxisY < -nThreshold && sAxisX < -nThreshold)
{
if (fCurAngle > (270.0f - 45.0f - ANGLE_RANGE) && fCurAngle < (270.0f - 45.0f + ANGLE_RANGE))
{
axisResult.Left = 1;
axisResult.Down = 1;
}
}
// 右下
if (sAxisY < -nThreshold && sAxisX > nThreshold)
{
if (fCurAngle > (270.0f + 45.0f - ANGLE_RANGE) && fCurAngle < (270.0f + 45.0f + ANGLE_RANGE))
{
axisResult.Right = 1;
axisResult.Down = 1;
}
}
return axisResult;
}
void CXInputHelper::_UpdateButtonState(GAMEPAD_INPUT_EVENT& event, const XINPUT_GAMEPAD& gamepad)
{
eGamepadButton& eButton = event.eButton;
event.curButtonState.Button = 0;
// 左扳机
if (eGamepadButton::eGamepad_LT & eButton)
{
if (gamepad.bLeftTrigger)
{
event.curButtonState.LT = 1;
}
}
// 右扳机
else if (eGamepadButton::eGamepad_RT & eButton)
{
if (gamepad.bRightTrigger)
{
event.curButtonState.RT = 1;
}
}
// 左摇杆
else if (eGamepadButton::eGamepad_LS & eButton)
{
GAMEPAD_AXIS_STATE axisState = _ParseAxisState(gamepad.sThumbLX, gamepad.sThumbLY, m_LeftAxisThreshold);
event.curButtonState.LS_Up = axisState.Up;
event.curButtonState.LS_Down = axisState.Down;
event.curButtonState.LS_Left = axisState.Left;
event.curButtonState.LS_Right = axisState.Right;
if (axisState.State)
{
event.curButtonState.LS = 1;
}
}
// 右摇杆
else if (eGamepadButton::eGamepad_RS & eButton)
{
GAMEPAD_AXIS_STATE axisState = _ParseAxisState(gamepad.sThumbRX, gamepad.sThumbRY, m_RightAxisThreshold);
event.curButtonState.RS_Up = axisState.Up;
event.curButtonState.RS_Down = axisState.Down;
event.curButtonState.RS_Left = axisState.Left;
event.curButtonState.RS_Right = axisState.Right;
if (axisState.State)
{
event.curButtonState.RS = 1;
}
}
else
{
event.curButtonState.Button |= (eButton & gamepad.wButtons);
}
}
void CXInputHelper::_UpdateAxisEvent(GAMEPAD_BUTTON_EVENT& event, bool fCur, bool fLast)
{
clock_t curTime = ::clock();
event.Down = false;
event.Up = false;
event.Hold = false;
// 按下
if (fCur && !fLast)
{
event.Down = true;
event.uTime = curTime;
event.uDuration = 0;
}
// 弹起
if (!fCur && fLast)
{
event.Up = true;
event.uDuration = curTime - event.uTime;
}
// 按住
if (fCur && fLast)
{
event.Hold = true;
event.uDuration = curTime - event.uTime;
}
// 无
if (!fCur && !fLast)
{
event.uTime = 0;
event.uDuration = 0;
}
}
void CXInputHelper::_UpdateButtonEvent(GAMEPAD_INPUT_EVENT& event, const XINPUT_GAMEPAD& gamepad)
{
eGamepadButton& eButton = event.eButton;
clock_t curTime = ::clock();
event.curButtonEvent.Event = 0;
bool curDown = false;
bool lastDown = false;
// 左扳机
if (eGamepadButton::eGamepad_LT & eButton)
{
curDown = event.curButtonState.LT;
lastDown = event.lastButtonState.LT;
}
// 右扳机
else if (eGamepadButton::eGamepad_RT & eButton)
{
curDown = event.curButtonState.RT;
lastDown = event.lastButtonState.RT;
}
// 左摇杆
else if (eGamepadButton::eGamepad_LS & eButton)
{
event.curAxisEvent.curAxisState = _ParseAxisState(gamepad.sThumbLX, gamepad.sThumbLY, m_LeftAxisThreshold);
event.curButtonState.LS_Up = event.curAxisEvent.curAxisState.Up;
event.curButtonState.LS_Down = event.curAxisEvent.curAxisState.Down;
event.curButtonState.LS_Left = event.curAxisEvent.curAxisState.Left;
event.curButtonState.LS_Right = event.curAxisEvent.curAxisState.Right;
curDown = event.curAxisEvent.curAxisState.State;
lastDown = event.curAxisEvent.lastAxisState.State;
_UpdateAxisEvent(event.curAxisEvent.Up, event.curAxisEvent.curAxisState.Up, event.curAxisEvent.lastAxisState.Up);
_UpdateAxisEvent(event.curAxisEvent.Down, event.curAxisEvent.curAxisState.Down, event.curAxisEvent.lastAxisState.Down);
_UpdateAxisEvent(event.curAxisEvent.Left, event.curAxisEvent.curAxisState.Left, event.curAxisEvent.lastAxisState.Left);
_UpdateAxisEvent(event.curAxisEvent.Right, event.curAxisEvent.curAxisState.Right, event.curAxisEvent.lastAxisState.Right);
}
// 右摇杆
else if (eGamepadButton::eGamepad_RS & eButton)
{
event.curAxisEvent.curAxisState = _ParseAxisState(gamepad.sThumbRX, gamepad.sThumbRY, m_RightAxisThreshold);
event.curButtonState.RS_Up = event.curAxisEvent.curAxisState.Up;
event.curButtonState.RS_Down = event.curAxisEvent.curAxisState.Down;
event.curButtonState.RS_Left = event.curAxisEvent.curAxisState.Left;
event.curButtonState.RS_Right = event.curAxisEvent.curAxisState.Right;
curDown = event.curAxisEvent.curAxisState.State;
lastDown = event.curAxisEvent.lastAxisState.State;
_UpdateAxisEvent(event.curAxisEvent.Up, event.curAxisEvent.curAxisState.Up, event.curAxisEvent.lastAxisState.Up);
_UpdateAxisEvent(event.curAxisEvent.Down, event.curAxisEvent.curAxisState.Down, event.curAxisEvent.lastAxisState.Down);
_UpdateAxisEvent(event.curAxisEvent.Left, event.curAxisEvent.curAxisState.Left, event.curAxisEvent.lastAxisState.Left);
_UpdateAxisEvent(event.curAxisEvent.Right, event.curAxisEvent.curAxisState.Right, event.curAxisEvent.lastAxisState.Right);
}
else
{
curDown = event.curButtonState.Button & eButton;
lastDown = event.lastButtonState.Button & eButton;
}
// 按下
if (curDown && !lastDown)
{
event.curButtonEvent.Down = true;
event.curButtonEvent.uTime = curTime;
event.curButtonEvent.uDuration = 0;
}
// 按住
if (curDown && lastDown)
{
event.curButtonEvent.Hold = true;
event.curButtonEvent.uDuration = curTime - event.curButtonEvent.uTime;
}
// 弹起
if (!curDown && lastDown)
{
event.curButtonEvent.Up = true;
event.curButtonEvent.uDuration = curTime - event.curButtonEvent.uTime;
}
event.lastButtonState = event.curButtonState;
event.curAxisEvent.lastAxisState = event.curAxisEvent.curAxisState;
}
void CXInputHelper::_InputEventProcess(uint32_t uIndex)
{
// 状态处理 & 事件处理
for (auto& item : m_buttonEvents[uIndex])
{
GAMEPAD_EVENT_CB_INFO& cbInfo = item.second;
cbInfo.eventState.eButton = item.first;
// 更新按钮状态
_UpdateButtonState(cbInfo.eventState, m_CurXInputStateIndex[uIndex].Gamepad);
// 更新按钮事件
_UpdateButtonEvent(cbInfo.eventState, m_CurXInputStateIndex[uIndex].Gamepad);
}
// 得到全部输入状态
m_CurButtonStateIndex[uIndex].Button = 0;
for (auto& item : m_buttonEvents[uIndex])
{
GAMEPAD_EVENT_CB_INFO& cbInfo = item.second;
if (eGamepadButton::eGamepad_LT & item.first)
{
m_CurButtonStateIndex[uIndex].LT = cbInfo.eventState.curButtonEvent.Down || cbInfo.eventState.curButtonEvent.Hold;
}
else if (eGamepadButton::eGamepad_RT & item.first)
{
m_CurButtonStateIndex[uIndex].RT = cbInfo.eventState.curButtonEvent.Down || cbInfo.eventState.curButtonEvent.Hold;
}
else if (eGamepadButton::eGamepad_LS & item.first)
{
m_CurButtonStateIndex[uIndex].LS = cbInfo.eventState.curButtonState.LS;
m_CurButtonStateIndex[uIndex].LS_Up = cbInfo.eventState.curButtonState.LS_Up;
m_CurButtonStateIndex[uIndex].LS_Down = cbInfo.eventState.curButtonState.LS_Down;
m_CurButtonStateIndex[uIndex].LS_Left = cbInfo.eventState.curButtonState.LS_Left;
m_CurButtonStateIndex[uIndex].LS_Right = cbInfo.eventState.curButtonState.LS_Right;
}
else if (eGamepadButton::eGamepad_RS & item.first)
{
m_CurButtonStateIndex[uIndex].RS = cbInfo.eventState.curButtonState.RS;
m_CurButtonStateIndex[uIndex].RS_Up = cbInfo.eventState.curButtonState.RS_Up;
m_CurButtonStateIndex[uIndex].RS_Down = cbInfo.eventState.curButtonState.RS_Down;
m_CurButtonStateIndex[uIndex].RS_Left = cbInfo.eventState.curButtonState.RS_Left;
m_CurButtonStateIndex[uIndex].RS_Right = cbInfo.eventState.curButtonState.RS_Right;
}
else
{
m_CurButtonStateIndex[uIndex].Button |= (cbInfo.eventState.curButtonEvent.Down || cbInfo.eventState.curButtonEvent.Hold) ? item.first : 0;
}
}
// 回调处理
for (auto& item : m_buttonEvents[uIndex])
{
GAMEPAD_EVENT_CB_INFO& cbInfo = item.second;
cbInfo.eventState.uIndex = uIndex;
cbInfo.eventState.curButtonState.Button = m_CurButtonStateIndex[uIndex].Button;
if (cbInfo.eventState.curButtonEvent.Event)
{
cbInfo.eventState.xinputState = m_CurXInputStateIndex[uIndex];
if (eGamepadButton::eGamepad_LT & item.first)
{
cbInfo.eventState.bTrigger = m_CurXInputStateIndex[uIndex].Gamepad.bLeftTrigger;
}
else if (eGamepadButton::eGamepad_RT & item.first)
{
cbInfo.eventState.fRight = true;
cbInfo.eventState.bTrigger = m_CurXInputStateIndex[uIndex].Gamepad.bRightTrigger;
}
else if (eGamepadButton::eGamepad_LS & item.first)
{
cbInfo.eventState.sAxisX = m_CurXInputStateIndex[uIndex].Gamepad.sThumbLX;
cbInfo.eventState.sAxisY = m_CurXInputStateIndex[uIndex].Gamepad.sThumbLY;
}
else if (eGamepadButton::eGamepad_RT & item.first)
{
cbInfo.eventState.fRight = true;
cbInfo.eventState.sAxisX = m_CurXInputStateIndex[uIndex].Gamepad.sThumbRX;
cbInfo.eventState.sAxisY = m_CurXInputStateIndex[uIndex].Gamepad.sThumbRY;
}
else if (eGamepadButton::eGamepad_RB & item.first)
{
cbInfo.eventState.fRight = true;
}
else if (eGamepadButton::eGamepad_RSB & item.first)
{
cbInfo.eventState.fRight = true;
}
(this->*(cbInfo.cbEvent))(cbInfo.eventState);
if (m_cbRawEvent)
{
m_cbRawEvent(cbInfo.eventState);
}
}
}
}
void CXInputHelper::_InputMergeProcess()
{
int32_t nThumbLX = 0;
int32_t nThumbLY = 0;
int32_t nThumbRX = 0;
int32_t nThumbRY = 0;
uint32_t nLeftTrigger = 0;
uint32_t nRightTrigger = 0;
// 混合输入按钮状态
m_CurXInputStateMerge.Gamepad.wButtons = 0;
for (uint32_t i = 0; i < XUSER_MAX_COUNT; ++i)
{
m_CurXInputStateMerge.Gamepad.wButtons |= m_CurXInputStateIndex[i].Gamepad.wButtons;
nThumbLX += m_CurXInputStateIndex[i].Gamepad.sThumbLX;
nThumbLY += m_CurXInputStateIndex[i].Gamepad.sThumbLY;
nThumbRX += m_CurXInputStateIndex[i].Gamepad.sThumbRX;
nThumbRY += m_CurXInputStateIndex[i].Gamepad.sThumbRY;
nLeftTrigger += m_CurXInputStateIndex[i].Gamepad.bLeftTrigger;
nRightTrigger += m_CurXInputStateIndex[i].Gamepad.bRightTrigger;
}
// 扳机有效范围限定
if (nLeftTrigger > UINT8_MAX) nLeftTrigger = UINT8_MAX;
if (nRightTrigger > UINT8_MAX) nRightTrigger = UINT8_MAX;
// 左摇杆轴有效范围限定
if (nThumbLX < INT16_MIN) nThumbLX = INT16_MIN;
if (nThumbLY < INT16_MIN) nThumbLY = INT16_MIN;
if (nThumbRX < INT16_MIN) nThumbRX = INT16_MIN;
if (nThumbRY < INT16_MIN) nThumbRY = INT16_MIN;
// 右摇杆轴有效范围限定
if (nThumbLX > INT16_MAX) nThumbLX = INT16_MAX;
if (nThumbLY > INT16_MAX) nThumbLY = INT16_MAX;
if (nThumbRX > INT16_MAX) nThumbRX = INT16_MAX;
if (nThumbRY > INT16_MAX) nThumbRY = INT16_MAX;
m_CurXInputStateMerge.Gamepad.bLeftTrigger = nLeftTrigger;
m_CurXInputStateMerge.Gamepad.bRightTrigger = nRightTrigger;
m_CurXInputStateMerge.Gamepad.sThumbLX = nThumbLX;
m_CurXInputStateMerge.Gamepad.sThumbLY = nThumbLY;
m_CurXInputStateMerge.Gamepad.sThumbRX = nThumbRX;
m_CurXInputStateMerge.Gamepad.sThumbRY = nThumbRY;
if (m_cbMergeState)
{
m_cbMergeState(m_CurXInputStateMerge.Gamepad);
}
}
void CXInputHelper::_InputMergeEventProcess()
{
// 状态处理 & 事件处理
for (auto& item : m_mergeEvents)
{
GAMEPAD_EVENT_CB_INFO& cbInfo = item.second;
cbInfo.eventState.eButton = item.first;
// 更新按钮状态
_UpdateButtonState(cbInfo.eventState, m_CurXInputStateMerge.Gamepad);
// 更新按钮事件
_UpdateButtonEvent(cbInfo.eventState, m_CurXInputStateMerge.Gamepad);
}
// 得到全部输入状态
m_CurButtonStateMerge.Button = 0;
for (auto& item : m_mergeEvents)
{
GAMEPAD_EVENT_CB_INFO& cbInfo = item.second;
if (eGamepadButton::eGamepad_LT & item.first)
{
m_CurButtonStateMerge.LT = cbInfo.eventState.curButtonEvent.Down || cbInfo.eventState.curButtonEvent.Hold;
}
else if (eGamepadButton::eGamepad_RT & item.first)
{
m_CurButtonStateMerge.RT = cbInfo.eventState.curButtonEvent.Down || cbInfo.eventState.curButtonEvent.Hold;
}
else if (eGamepadButton::eGamepad_LS & item.first)
{
m_CurButtonStateMerge.LS = cbInfo.eventState.curButtonState.LS;
m_CurButtonStateMerge.LS_Up = cbInfo.eventState.curButtonState.LS_Up;
m_CurButtonStateMerge.LS_Down = cbInfo.eventState.curButtonState.LS_Down;
m_CurButtonStateMerge.LS_Left = cbInfo.eventState.curButtonState.LS_Left;
m_CurButtonStateMerge.LS_Right = cbInfo.eventState.curButtonState.LS_Right;
cbInfo.eventState.sAxisX = m_CurXInputStateMerge.Gamepad.sThumbLX;
cbInfo.eventState.sAxisY = m_CurXInputStateMerge.Gamepad.sThumbLY;
}
else if (eGamepadButton::eGamepad_RS & item.first)
{
m_CurButtonStateMerge.RS = cbInfo.eventState.curButtonState.RS;
m_CurButtonStateMerge.RS_Up = cbInfo.eventState.curButtonState.RS_Up;
m_CurButtonStateMerge.RS_Down = cbInfo.eventState.curButtonState.RS_Down;
m_CurButtonStateMerge.RS_Left = cbInfo.eventState.curButtonState.RS_Left;
m_CurButtonStateMerge.RS_Right = cbInfo.eventState.curButtonState.RS_Right;
cbInfo.eventState.sAxisX = m_CurXInputStateMerge.Gamepad.sThumbRX;
cbInfo.eventState.sAxisY = m_CurXInputStateMerge.Gamepad.sThumbRY;
}
else
{
m_CurButtonStateMerge.Button |= (cbInfo.eventState.curButtonEvent.Down || cbInfo.eventState.curButtonEvent.Hold) ? item.first : 0;
}
}
// 回调处理
for (auto& item : m_mergeEvents)
{
GAMEPAD_EVENT_CB_INFO& cbInfo = item.second;
cbInfo.eventState.curButtonState.Button = m_CurButtonStateMerge.Button;
if (cbInfo.eventState.curButtonEvent.Event)
{
cbInfo.eventState.xinputState = m_CurXInputStateMerge;
if (eGamepadButton::eGamepad_LT & item.first)
{
cbInfo.eventState.bTrigger = m_CurXInputStateMerge.Gamepad.bLeftTrigger;
}
else if (eGamepadButton::eGamepad_RT & item.first)
{
cbInfo.eventState.fRight = true;
cbInfo.eventState.bTrigger = m_CurXInputStateMerge.Gamepad.bRightTrigger;
}
else if (eGamepadButton::eGamepad_LS & item.first)
{
cbInfo.eventState.sAxisX = m_CurXInputStateMerge.Gamepad.sThumbLX;
cbInfo.eventState.sAxisY = m_CurXInputStateMerge.Gamepad.sThumbLY;
}
else if (eGamepadButton::eGamepad_RS & item.first)
{
cbInfo.eventState.fRight = true;
cbInfo.eventState.sAxisX = m_CurXInputStateMerge.Gamepad.sThumbRX;
cbInfo.eventState.sAxisY = m_CurXInputStateMerge.Gamepad.sThumbRY;
}
else if (eGamepadButton::eGamepad_RB & item.first)
{
cbInfo.eventState.fRight = true;
}
else if (eGamepadButton::eGamepad_RSB & item.first)
{
cbInfo.eventState.fRight = true;
}
(this->*(cbInfo.cbEvent))(cbInfo.eventState);
if (m_cbMergeEvent)
{
m_cbMergeEvent(cbInfo.eventState);
}
}
}
}
main.cpp
#include <string>
#include <iostream>
#include <windows.h>
#include <tchar.h>
#include "CWin32Utils/CXinputHelper.h"
#include "CMainFrame.h"
#include "resource.h"
#ifdef _UNICODE
using _tstring = std::wstring;
#else
using _tstring = std::string;
#endif
int WINAPI WinMain(
_In_ HINSTANCE hInstance,
_In_opt_ HINSTANCE hPrevInstance,
_In_ LPSTR lpCmdLine,
_In_ int nShowCmd)
{
UNREFERENCED_PARAMETER(hInstance);
UNREFERENCED_PARAMETER(hPrevInstance);
UNREFERENCED_PARAMETER(lpCmdLine);
UNREFERENCED_PARAMETER(nShowCmd);
CMainFrame dlg;
dlg.DoModalEx(IDD_DIALOG_MAIN, NULL, TRUE, true);
return 0;
}
int main()
{
CXInputHelper obj;
obj.Initialize();
//obj.SetAxisThreshold(4096, 4096);
#if 0
obj.SetRawEventCallback([](const GAMEPAD_INPUT_EVENT& event)-> void {
CXInputHelper::PrintText(_T("Mask: %08X bRight: %d Trigger: %3d Axis: %6d,%6d Data: %d Buttons: %.8X Duration: %6d Axis: (Left: %d Up: %d Right: %d Down: %d)\r\n"),
event.eButton,
event.fRight, event.bTrigger,
event.sAxisX, event.sAxisY,
event.curButtonEvent.Event,
event.curButtonState.Button,
event.curButtonEvent.uDuration,
event.curAxisEvent.Left.Event,
event.curAxisEvent.Up.Event,
event.curAxisEvent.Right.Event,
event.curAxisEvent.Down.Event
);
}
);
#endif
obj.SetMergeEventCallback([](const GAMEPAD_INPUT_EVENT& event)-> void {
CXInputHelper::PrintText(_T("Mask: %08X bRight: %d Trigger: %3d Axis: %6d,%6d Data: %d Buttons: %.8X Duration: %6d Axis: (Left: %d Up: %d Right: %d Down: %d)\r\n"),
event.eButton,
event.fRight, event.bTrigger,
event.sAxisX, event.sAxisY,
event.curButtonEvent.Event,
event.curButtonState.Button,
event.curButtonEvent.uDuration,
event.curAxisEvent.Left.Event,
event.curAxisEvent.Up.Event,
event.curAxisEvent.Right.Event,
event.curAxisEvent.Down.Event
);
}
);
system("pause");
return 0;
}
测试