Xinput辅助封装

49 篇文章 0 订阅

CXinputHelper.h

#pragma once
#include <windows.h>
#include <xinput.h>
#include <tchar.h>
#include <thread>
#include <functional>
#include <string>
#pragma comment(lib, "xinput.lib")

#ifdef _UNICODE
using _tstring = std::wstring;
#else
using _tstring = std::string;
#endif

// 单个变化状态
typedef struct _GAMEPAD_INFO
{
    DWORD dwIndex;      // 当前手柄索引
    WORD wButton;       // 当前触发的单个按键
    SHORT sThumbX;      // 当前摇杆X值
    SHORT sThumbY;      // 当前摇杆Y值
    BYTE bTrigger;      // 扳机数据
    bool bRight;        // 是否为右摇杆/扳机(false: 左, true: 右)
    bool bPress;        // 是否触发按钮按下(从未按下 -> 按下)
    bool bRelease;      // 是否触发按钮释放(从按下 -> 未按下)
    bool bHolding;      // 按住触发按钮按住(从按下 -> 按下)
}GAMEPAD_INFO;

class CXInputHelper
{
public:

    CXInputHelper();
    virtual ~CXInputHelper();

    bool Initialize();

    void Uninitialize();

    void IgnoreLeftThumbEmpty(
        bool bEnable = true                     // 允许空数据触发回调
    );

    void IgnoreRightThumbEmpty(
        bool bEnable = true                     // 允许空数据触发回调
    );

    void SetThumbThreshold(
        int nThumbThreshold = 500               // 摇杆触发阈值(死区)
    );

    // 设置检测每个控制器输入数据回调
    void SetSingleStateCallback(
        std::function<void(
            DWORD dwIndex,                      // 控制器索引(有效值: 0 - 3)
            const XINPUT_GAMEPAD& xGamepad      // 控制器数据
            )> cb
    );

    // 设置合并多个控制器输入数据回调
    void SetMergeStateCallback(
        std::function<void(
            const XINPUT_GAMEPAD& xGamepad      // 控制器数据
            )> cb
    );

    // 设置检测每个控制器输入状态变化回调(发生按钮按下, 释放, 按住时触发)
    void SetSingleChangeCallback(
        std::function<void(
            const XINPUT_GAMEPAD& xGamepad,     // 原始控制器数据
            const GAMEPAD_INFO& state           // 回调信息
            )> cb
    );

    // 设置合并多个控制器输入状态变化回调(发生按钮按下, 释放, 按住时触发)
    void SetMergeChangeCallback(
        std::function<void(
            const XINPUT_GAMEPAD& xGamepad,     // 原始控制器数据
            const GAMEPAD_INFO& state           // 回调信息
            )> cb
    );

    // 方向键回调
    virtual bool OnButtonDpadUp(const XINPUT_GAMEPAD& xGamepad, const GAMEPAD_INFO& state);
    virtual bool OnButtonDpadDown(const XINPUT_GAMEPAD& xGamepad, const GAMEPAD_INFO& state);
    virtual bool OnButtonDpadLeft(const XINPUT_GAMEPAD& xGamepad, const GAMEPAD_INFO& state);
    virtual bool OnButtonDpadRight(const XINPUT_GAMEPAD& xGamepad, const GAMEPAD_INFO& state);

    // 返回键, 开始键回调
    virtual bool OnButtonBack(const XINPUT_GAMEPAD& xGamepad, const GAMEPAD_INFO& state);
    virtual bool OnButtonStart(const XINPUT_GAMEPAD& xGamepad, const GAMEPAD_INFO& state);

    // XYBA回调
    virtual bool OnButtonA(const XINPUT_GAMEPAD& xGamepad, const GAMEPAD_INFO& state);
    virtual bool OnButtonB(const XINPUT_GAMEPAD& xGamepad, const GAMEPAD_INFO& state);
    virtual bool OnButtonX(const XINPUT_GAMEPAD& xGamepad, const GAMEPAD_INFO& state);
    virtual bool OnButtonY(const XINPUT_GAMEPAD& xGamepad, const GAMEPAD_INFO& state);

    // 肩键回调
    virtual bool OnButtonLeftShoulder(const XINPUT_GAMEPAD& xGamepad, const GAMEPAD_INFO& state);
    virtual bool OnButtonRightShoulder(const XINPUT_GAMEPAD& xGamepad, const GAMEPAD_INFO& state);

    // 拇指按键回调
    virtual bool OnButtonLeftThumb(const XINPUT_GAMEPAD& xGamepad, const GAMEPAD_INFO& state);
    virtual bool OnButtonRightThumb(const XINPUT_GAMEPAD& xGamepad, const GAMEPAD_INFO& state);

    // 扳机回调
    virtual bool OnLeftTrigger(const XINPUT_GAMEPAD& xGamepad, const GAMEPAD_INFO& state);
    virtual bool OnRightTrigger(const XINPUT_GAMEPAD& xGamepad, const GAMEPAD_INFO& state);

    // 拇指摇杆回调
    virtual bool OnLeftThumb(const XINPUT_GAMEPAD& xGamepad, const GAMEPAD_INFO& state);
    virtual bool OnRightThumb(const XINPUT_GAMEPAD& xGamepad, const GAMEPAD_INFO& state);

    // 打印状态信息
    virtual void PrintState(const GAMEPAD_INFO& state);

    // 打印
    void PrintText(LPCTSTR pFormat, ...);

private:

    // 任务循环
    void _GamepadLoop();

    // 睡眠间隔
    void _Sleep(int millisecond);

private:

    std::function<void(DWORD dwIndex, const XINPUT_GAMEPAD& xGamepad)> m_cbSingleState;                 // 检测每个控制器输入数据回调
    std::function<void(const XINPUT_GAMEPAD& xGamepad)> m_cbMergeState;                                 // 合并多个控制器输入数据回调
    std::function<void(const XINPUT_GAMEPAD& xGamepad, const GAMEPAD_INFO& state)> m_cbSingleChange;    // 检测每个控制器输入状态变化回调(发生按钮按下, 释放, 按住时触发)
    std::function<void(const XINPUT_GAMEPAD& xGamepad, const GAMEPAD_INFO& state)> m_cbMergeChange;     // 合并多个控制器输入状态变化回调(发生按钮按下, 释放, 按住时触发)

    std::thread m_gamepadTask;      // 控制器状态检测任务线程
    int m_ThumbThreshold;           // 摇杆触发阈值
    bool m_bIgnoreLeftThumbEmpty;   // 左摇杆 X,Y 轴数据均为 0 时也触发回调
    bool m_bIgnoreRightThumbEmpty;  // 右摇杆 X,Y 轴数据均为 0 时也触发回调
    bool m_fQuit = false;           // 退出标志
};

CXinputHelper.cpp

#include "CXinputHelper.h"
#include <stdint.h>
#include <Winerror.h>
#include <map>

CXInputHelper::CXInputHelper()
    :
    m_bIgnoreLeftThumbEmpty(true),
    m_bIgnoreRightThumbEmpty(true),
    m_fQuit(false),
    m_ThumbThreshold(200)
{

}

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::IgnoreLeftThumbEmpty(
    bool bEnable
)
{
    m_bIgnoreLeftThumbEmpty = bEnable;
}

void CXInputHelper::IgnoreRightThumbEmpty(
    bool bEnable
)
{
    m_bIgnoreRightThumbEmpty = bEnable;
}

void CXInputHelper::SetThumbThreshold(
    int nThumbThreshold/* = 500*/
)
{
    m_ThumbThreshold = nThumbThreshold;
}

void CXInputHelper::SetSingleStateCallback(
    std::function<void(
        DWORD dwIndex,
        const XINPUT_GAMEPAD& xGamepad
        )> cb
)
{
    m_cbSingleState = cb;
}

void CXInputHelper::SetMergeStateCallback(
    std::function<void(
        const XINPUT_GAMEPAD& xGamepad
        )> cb
)
{
    m_cbMergeState = cb;
}

void CXInputHelper::SetSingleChangeCallback(
    std::function<void(
        const XINPUT_GAMEPAD& xGamepad,
        const GAMEPAD_INFO& state
        )> cb
)
{
    m_cbSingleChange = cb;
}

void CXInputHelper::SetMergeChangeCallback(
    std::function<void(
        const XINPUT_GAMEPAD& xGamepad,
        const GAMEPAD_INFO& state
        )> cb
)
{
    m_cbMergeChange = cb;
}

void CXInputHelper::_Sleep(int millisecond)
{
    const int span = 10;
    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));
    }
}

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);
}
void CXInputHelper::_GamepadLoop()
{
    typedef bool (CXInputHelper::* pFn)(const XINPUT_GAMEPAD& data, const GAMEPAD_INFO& state);
    static std::map<DWORD, pFn> buttonEvents = {
        {XINPUT_GAMEPAD_A,                          &CXInputHelper::OnButtonA},
        {XINPUT_GAMEPAD_B,                          &CXInputHelper::OnButtonB},
        {XINPUT_GAMEPAD_X,                          &CXInputHelper::OnButtonX},
        {XINPUT_GAMEPAD_Y,                          &CXInputHelper::OnButtonY},
        {XINPUT_GAMEPAD_BACK,                       &CXInputHelper::OnButtonBack},
        {XINPUT_GAMEPAD_START,                      &CXInputHelper::OnButtonStart},
        {XINPUT_GAMEPAD_DPAD_UP,                    &CXInputHelper::OnButtonDpadUp},
        {XINPUT_GAMEPAD_DPAD_DOWN,                  &CXInputHelper::OnButtonDpadDown},
        {XINPUT_GAMEPAD_DPAD_LEFT,                  &CXInputHelper::OnButtonDpadLeft},
        {XINPUT_GAMEPAD_DPAD_RIGHT,                 &CXInputHelper::OnButtonDpadRight},
        {XINPUT_GAMEPAD_LEFT_SHOULDER,              &CXInputHelper::OnButtonLeftShoulder},
        {XINPUT_GAMEPAD_RIGHT_SHOULDER,             &CXInputHelper::OnButtonRightShoulder},
        {XINPUT_GAMEPAD_LEFT_THUMB,                 &CXInputHelper::OnButtonLeftThumb},
        {XINPUT_GAMEPAD_RIGHT_THUMB,                &CXInputHelper::OnButtonRightThumb}
    };

    XINPUT_STATE xLastStateArray[XUSER_MAX_COUNT] = { 0 };
    XINPUT_STATE xLastStateMixed = { 0 };
    LONG nLastThumbLX = 0;
    LONG nLastThumbLY = 0;
    LONG nLastThumbRX = 0;
    LONG nLastThumbRY = 0;
    LONG nLastLeftTrigger = 0;
    LONG nLastRightTrigger = 0;

    // 按钮检测
    auto HitButtonState = [this](bool& bPress, bool& bRelease, bool& bHolding, const XINPUT_GAMEPAD& last, const XINPUT_GAMEPAD& cur, WORD wButton) {

        bPress = false;
        bRelease = false;
        bHolding = false;

        if ((0 == (last.wButtons & wButton)) && (cur.wButtons & wButton)) bPress = true;
        if ((last.wButtons & wButton) && (0 == (cur.wButtons & wButton))) bRelease = true;
        if ((last.wButtons & wButton) && (cur.wButtons & wButton)) bHolding = true;

        };

    // 扳机检测
    auto HitTriggerState = [this](bool& bPress, bool& bRelease, bool& bHolding, const LONG& nTrigger, const LONG& nLastTrigger) {

        bPress = false;
        bRelease = false;
        bHolding = false;

        if (0 == nLastTrigger && nTrigger) bPress = true;
        if (nLastTrigger && 0 == nTrigger) bRelease = true;
        if (nLastTrigger && nTrigger) bHolding = true;

        };

    while (!m_fQuit)
    {
        XINPUT_STATE xCurStateArray[XUSER_MAX_COUNT] = { 0 };
        XINPUT_STATE xCurStateMixed = { 0 };
        LONG nThumbLX = 0;
        LONG nThumbLY = 0;
        LONG nThumbRX = 0;
        LONG nThumbRY = 0;
        LONG nLeftTrigger = 0;
        LONG nRightTrigger = 0;

        // 遍历控制器输入
        for (int i = 0; i < XUSER_MAX_COUNT; ++i)
        {
            XINPUT_STATE xTmpState = { 0 };
            DWORD dwResult = ::XInputGetState(i, &xTmpState);

            //触发值限定
            if (abs(xTmpState.Gamepad.sThumbLX) < m_ThumbThreshold) xTmpState.Gamepad.sThumbLX = 0;
            if (abs(xTmpState.Gamepad.sThumbLY) < m_ThumbThreshold) xTmpState.Gamepad.sThumbLY = 0;
            if (abs(xTmpState.Gamepad.sThumbRX) < m_ThumbThreshold) xTmpState.Gamepad.sThumbRX = 0;
            if (abs(xTmpState.Gamepad.sThumbRY) < m_ThumbThreshold) xTmpState.Gamepad.sThumbRY = 0;

            xCurStateArray[i] = xTmpState;

            //未连接控制器
            if (ERROR_DEVICE_NOT_CONNECTED == dwResult)
            {
                xLastStateArray[i] = xCurStateArray[i];
                continue;
            }

            // 累加多输入数据
            {
                xCurStateMixed.Gamepad.wButtons |= xTmpState.Gamepad.wButtons;
                nLeftTrigger += xTmpState.Gamepad.bLeftTrigger;
                nRightTrigger += xTmpState.Gamepad.bRightTrigger;
                nThumbLX += xTmpState.Gamepad.sThumbLX;
                nThumbLY += xTmpState.Gamepad.sThumbLY;
                nThumbRX += xTmpState.Gamepad.sThumbRX;
                nThumbRY += xTmpState.Gamepad.sThumbRY;
            }

            //连接控制器
            if (ERROR_SUCCESS == dwResult)
            {
                // 单控制器输入回调
                if (m_cbSingleState)
                {
                    m_cbSingleState(i, xTmpState.Gamepad);
                }

                // 单控制器变化回调
                if (m_cbSingleChange)
                {
                    XINPUT_GAMEPAD& lastState = xLastStateArray[i].Gamepad;
                    XINPUT_GAMEPAD& curState = xCurStateArray[i].Gamepad;

                    // 按键变化处理
                    for (const auto& item : buttonEvents)
                    {
                        GAMEPAD_INFO state = { 0 };
                        state.dwIndex = i;

                        bool bPress = false;
                        bool bRelease = false;
                        bool bHolding = false;

                        HitButtonState(bPress, bRelease, bHolding, lastState, curState, item.first);
                        if (bPress || bRelease || bHolding)
                        {
                            state.bPress = bPress;
                            state.bRelease = bRelease;
                            state.bHolding = bHolding;
                            state.wButton = item.first;
                            m_cbSingleChange(curState, state);
                        }
                    }

                    // 扳机变化处理
                    {
                        bool bPress = false;
                        bool bRelease = false;
                        bool bHolding = false;

                        // 左扳机
                        HitTriggerState(bPress, bRelease, bHolding, curState.bLeftTrigger, lastState.bLeftTrigger);
                        if (bPress || bRelease || bHolding)
                        {
                            GAMEPAD_INFO state = { 0 };
                            state.dwIndex = i;
                            state.bPress = bPress;
                            state.bRelease = bRelease;
                            state.bHolding = bHolding;
                            state.bRight = false;
                            state.bTrigger = nLeftTrigger;

                            m_cbSingleChange(curState, state);
                        }

                        // 右扳机
                        HitTriggerState(bPress, bRelease, bHolding, curState.bRightTrigger, lastState.bRightTrigger);
                        if (bPress || bRelease || bHolding)
                        {
                            GAMEPAD_INFO state = { 0 };
                            state.dwIndex = i;
                            state.bPress = bPress;
                            state.bRelease = bRelease;
                            state.bHolding = bHolding;
                            state.bRight = true;
                            state.bTrigger = nRightTrigger;

                            m_cbSingleChange(curState, state);
                        }
                    }

                    // 摇杆变化处理
                    {
                        // 左摇杆
                        if (curState.sThumbLX || curState.sThumbLY || m_bIgnoreLeftThumbEmpty)
                        {
                            GAMEPAD_INFO state = { 0 };
                            state.dwIndex = i;
                            state.sThumbX = curState.sThumbLX;
                            state.sThumbY = curState.sThumbLY;
                            state.bRight = false;

                            m_cbSingleChange(curState, state);
                        }

                        // 右摇杆
                        if (curState.sThumbRX || curState.sThumbRY || m_bIgnoreRightThumbEmpty)
                        {
                            GAMEPAD_INFO state = { 0 };
                            state.dwIndex = i;
                            state.sThumbX = curState.sThumbRX;
                            state.sThumbY = curState.sThumbRY;
                            state.bRight = true;

                            m_cbSingleChange(curState, state);
                        }
                    }
                }
            }

            // 记录状态
            xLastStateArray[i] = xCurStateArray[i];
        }

        // 多输入合并
        {
            // 限制范围
            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;
            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 (nLeftTrigger > UINT8_MAX) nLeftTrigger = UINT8_MAX;
            if (nRightTrigger > UINT8_MAX) nRightTrigger = UINT8_MAX;

            xCurStateMixed.Gamepad.sThumbLX = nThumbLX;
            xCurStateMixed.Gamepad.sThumbLY = nThumbLY;
            xCurStateMixed.Gamepad.sThumbRX = nThumbRX;
            xCurStateMixed.Gamepad.sThumbRY = nThumbRY;
            xCurStateMixed.Gamepad.bLeftTrigger = nLeftTrigger;
            xCurStateMixed.Gamepad.bRightTrigger = nRightTrigger;
        }

        // 合并状态回调处理
        if (m_cbMergeState)
        {
            m_cbMergeState(xCurStateMixed.Gamepad);
        }

        // 按键变化处理
        for (const auto& item : buttonEvents)
        {
            bool bPress = false;
            bool bRelease = false;
            bool bHolding = false;

            HitButtonState(bPress, bRelease, bHolding, xLastStateMixed.Gamepad, xCurStateMixed.Gamepad, item.first);
            if (bPress || bRelease || bHolding)
            {
                GAMEPAD_INFO state = { 0 };
                state.bPress = bPress;
                state.bRelease = bRelease;
                state.bHolding = bHolding;
                state.wButton = item.first;

                (this->*item.second)(xCurStateMixed.Gamepad, state);

                // 合并数据变化回调
                if (m_cbMergeChange)
                {
                    m_cbMergeChange(xCurStateMixed.Gamepad, state);
                }
            }
        }

        // 扳机变化处理
        {
            bool bPress = false;
            bool bRelease = false;
            bool bHolding = false;

            // 左扳机
            HitTriggerState(bPress, bRelease, bHolding, nLeftTrigger, nLastLeftTrigger);
            if (bPress || bRelease || bHolding)
            {
                GAMEPAD_INFO state = { 0 };
                state.bPress = bPress;
                state.bRelease = bRelease;
                state.bHolding = bHolding;
                state.bRight = false;
                state.bTrigger = nLeftTrigger;

                OnLeftTrigger(xCurStateMixed.Gamepad, state);

                // 变化回调处理
                if (m_cbMergeChange)
                {
                    m_cbMergeChange(xCurStateMixed.Gamepad, state);
                }

            }

            // 右扳机
            HitTriggerState(bPress, bRelease, bHolding, nRightTrigger, nLastRightTrigger);
            if (bPress || bRelease || bHolding)
            {
                GAMEPAD_INFO state = { 0 };
                state.bPress = bPress;
                state.bRelease = bRelease;
                state.bHolding = bHolding;
                state.bRight = true;
                state.bTrigger = nRightTrigger;

                OnRightTrigger(xCurStateMixed.Gamepad, state);

                // 合并数据变化回调
                if (m_cbMergeChange)
                {
                    m_cbMergeChange(xCurStateMixed.Gamepad, state);
                }
            }
        }

        // 摇杆变化处理
        {
            // 左摇杆
            if (xCurStateMixed.Gamepad.sThumbLX || xCurStateMixed.Gamepad.sThumbLY || m_bIgnoreLeftThumbEmpty)
            {
                GAMEPAD_INFO state = { 0 };
                state.sThumbX = xCurStateMixed.Gamepad.sThumbLX;
                state.sThumbY = xCurStateMixed.Gamepad.sThumbLY;
                state.bRight = false;

                OnLeftThumb(xCurStateMixed.Gamepad, state);

                // 合并数据变化回调
                if (m_cbMergeChange)
                {
                    m_cbMergeChange(xCurStateMixed.Gamepad, state);
                }
            }

            // 右摇杆
            if (xCurStateMixed.Gamepad.sThumbRX || xCurStateMixed.Gamepad.sThumbRY || m_bIgnoreRightThumbEmpty)
            {
                GAMEPAD_INFO state = { 0 };
                state.sThumbX = xCurStateMixed.Gamepad.sThumbRX;
                state.sThumbY = xCurStateMixed.Gamepad.sThumbRY;
                state.bRight = true;

                OnRightThumb(xCurStateMixed.Gamepad, state);

                // 合并数据变化回调
                if (m_cbMergeChange)
                {
                    m_cbMergeChange(xCurStateMixed.Gamepad, state);
                }
            }
        }

        // 记录上次状态
        xLastStateMixed = xCurStateMixed;
        nLastThumbLX= nThumbLX;
        nLastThumbLY= nThumbLY;
        nLastThumbRX= nThumbRX;
        nLastThumbRY= nThumbRY;
        nLastLeftTrigger = nLeftTrigger ;
        nLastRightTrigger = nRightTrigger;

        _Sleep(10);
    }
}

bool CXInputHelper::OnButtonA(const XINPUT_GAMEPAD& xGamepad, const GAMEPAD_INFO& state)
{
    PrintState(state);
    return true;
}

bool CXInputHelper::OnButtonB(const XINPUT_GAMEPAD& xGamepad, const GAMEPAD_INFO& state)
{
    PrintState(state);
    return true;
}

bool CXInputHelper::OnButtonX(const XINPUT_GAMEPAD& xGamepad, const GAMEPAD_INFO& state)
{
    PrintState(state);
    return true;
}

bool CXInputHelper::OnButtonY(const XINPUT_GAMEPAD& xGamepad, const GAMEPAD_INFO& state)
{
    PrintState(state);
    return true;
}

bool CXInputHelper::OnButtonBack(const XINPUT_GAMEPAD& xGamepad, const GAMEPAD_INFO& state)
{
    PrintState(state);
    return true;
}

bool CXInputHelper::OnButtonStart(const XINPUT_GAMEPAD& xGamepad, const GAMEPAD_INFO& state)
{
    PrintState(state);
    return true;
}

bool CXInputHelper::OnButtonDpadUp(const XINPUT_GAMEPAD& xGamepad, const GAMEPAD_INFO& state)
{
    PrintState(state);
    return true;
}

bool CXInputHelper::OnButtonDpadDown(const XINPUT_GAMEPAD& xGamepad, const GAMEPAD_INFO& state)
{
    PrintState(state);
    return true;
}

bool CXInputHelper::OnButtonDpadLeft(const XINPUT_GAMEPAD& xGamepad, const GAMEPAD_INFO& state)
{
    PrintState(state);
    return true;
}

bool CXInputHelper::OnButtonDpadRight(const XINPUT_GAMEPAD& xGamepad, const GAMEPAD_INFO& state)
{
    PrintState(state);
    return true;
}

bool CXInputHelper::OnButtonLeftShoulder(const XINPUT_GAMEPAD& xGamepad, const GAMEPAD_INFO& state)
{
    PrintState(state);
    return true;
}

bool CXInputHelper::OnButtonRightShoulder(const XINPUT_GAMEPAD& xGamepad, const GAMEPAD_INFO& state)
{
    PrintState(state);
    return true;
}

bool CXInputHelper::OnButtonLeftThumb(const XINPUT_GAMEPAD& xGamepad, const GAMEPAD_INFO& state)
{
    PrintState(state);
    return true;
}

bool CXInputHelper::OnButtonRightThumb(const XINPUT_GAMEPAD& xGamepad, const GAMEPAD_INFO& state)
{
    PrintState(state);
    return true;
}

bool CXInputHelper::OnLeftTrigger(const XINPUT_GAMEPAD& xGamepad, const GAMEPAD_INFO& state)
{
    PrintState(state);
    return true;
}

bool CXInputHelper::OnRightTrigger(const XINPUT_GAMEPAD& xGamepad, const GAMEPAD_INFO& state)
{
    PrintState(state);
    return true;
}

bool CXInputHelper::OnLeftThumb(const XINPUT_GAMEPAD& xGamepad, const GAMEPAD_INFO& state)
{
    PrintState(state);
    return true;
}

bool CXInputHelper::OnRightThumb(const XINPUT_GAMEPAD& xGamepad, const GAMEPAD_INFO& state)
{
    PrintState(state);
    return true;
}

void CXInputHelper::PrintState(const GAMEPAD_INFO& state)
{
    return;
    PrintText(_T("OnRightThumb Index: %d bRight: %d Trigger: %3d %6d,%6d Button: %04X Press: %d Release: %d Holding: %d\r\n"),
        state.dwIndex, state.bRight, state.bTrigger, state.sThumbX, state.sThumbY, state.wButton, state.bPress, state.bRelease, state.bHolding);
}

测试:

main.cpp

// JoystickAssistant.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//

#include <string>
#include <iostream>
#include <windows.h>
#include <tchar.h>
#include "CXinputHelper.h"

#ifdef _UNICODE
using _tstring = std::wstring;
#else
using _tstring = std::string;
#endif

void LogPrintf(LPCTSTR pFormat, ...);

int main()
{
    CXInputHelper obj;

    obj.Initialize();

    obj.IgnoreLeftThumbEmpty(false);
    obj.IgnoreRightThumbEmpty(false);
    obj.SetThumbThreshold(4096);

    /*obj.SetSingleStateCallback([](DWORD dwIndex, const XINPUT_GAMEPAD& xGamepad)-> void {
        LogPrintf(_T("Index: %2d wButtons: %04X LT: %3d, RT: %3d LS: %6d,%6d RS: %6d,%6d \r\n"),
        dwIndex,
        xGamepad.wButtons,
        xGamepad.bLeftTrigger,
        xGamepad.bRightTrigger,
        xGamepad.sThumbLX, xGamepad.sThumbLY,
        xGamepad.sThumbRX, xGamepad.sThumbRY
        );

        }
    );*/

    /*obj.SetMergeStateCallback([](const XINPUT_GAMEPAD& xGamepad)-> void {
        LogPrintf(_T("%04X LT: %3d, RT: %3d LS: %6d,%6d RS: %6d,%6d \r\n"),
        xGamepad.wButtons,
        xGamepad.bLeftTrigger,
        xGamepad.bRightTrigger,
        xGamepad.sThumbLX, xGamepad.sThumbLY,
        xGamepad.sThumbRX, xGamepad.sThumbRY
        );

        }
    );*/

    obj.SetSingleChangeCallback([](const XINPUT_GAMEPAD& xGamepad, const GAMEPAD_INFO& state)-> void {
        LogPrintf(_T("Index: %d bRight: %d Trigger: %3d Thumb: %6d,%6d Button: %04X Press: %d Release: %d Holding: %d\r\n"),
        state.dwIndex,
        state.bRight, state.bTrigger, state.sThumbX, state.sThumbY, state.wButton, state.bPress, state.bRelease, state.bHolding);

        }
    );

    /*obj.SetMergeChangeCallback([](const XINPUT_GAMEPAD& xGamepad, const GAMEPAD_INFO& state)-> void {
        LogPrintf(_T("Index: %d bRight: %d Trigger: %3d %6d,%6d Button: %04X Press: %d Release: %d Holding: %d\r\n"), 
        state.dwIndex,
        state.bRight, state.bTrigger, state.sThumbX, state.sThumbY, state.wButton, state.bPress, state.bRelease, state.bHolding);

        }
    );*/

    system("pause");

    return 0;
}

void LogPrintf(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);
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值