USB手柄的控制
来源:互联网 发布:java多线程实现多任务 编辑:程序博客网 时间:2024/06/10 01:37
USB手柄的控制
Flyli
USB手柄或游戏控制杆并不一定只在打游戏的时候才用得到,为了控制以PC机为核心的机器人能够在手动的控制下运动,略微研究了下USB手柄的控制方法。
通过查阅相关资料,查到了2中USB手柄的控制方法,一种是基于windows DDK的USB开发,由于没有搞到DDK所以暂且不谈这种方法
我们来说说第二种方法,就是以基于DirectX8.1以上的USB手柄控制方法,使用这种方法需要下载Direct的SDK,运用到他的运行库。Dinput8.lib,DxErr.Lib,dxguid.lib另外还需要加载direct的一些头文件,至于头文件具体用到了那些我也没有测试,我把这些可能用到的程序都发到了我的资源中,地址是:http://download.csdn.net/source/402394
其中将所有的.h文件复制到vc的运行库下,把.lib文件加载到工程中就可以使用了。
其使用方法也是相当的简单:
1. 将CDirectInput实例化
2. 调用InitDirectInput初始化USB手柄,通过其返回值判断手柄是否被识别
3. 声明一个DIJOYSTATE2 类型的值用于接收按键的状态
4. 用GetState_Now()声明的DIJOYSTATE2的值进行赋值;
5. DIJOYSTATE2 中部分键值的对应关系 lx,ly分别是对应上下左右的方向,rgbbutton[]的数组是分别用来对应其他的手柄按键。
遇到具体的问题可以再联系我哈
一下是我封装后的类
//********************************************************************
// DirectInput.h 文件
//********************************************************************************
#pragma once
#define DIRECTINPUT_VERSION 0x0800
#define _CRT_SECURE_NO_DEPRECATE
#ifndef _WIN32_DCOM
#define _WIN32_DCOM
#endif
#include <windows.h>
#include <commctrl.h>
#include <basetsd.h>
#include <dinput.h>
#include <dinputd.h>
#include <assert.h>
#include <oleauto.h>
#include <shellapi.h>
#include <wbemidl.h>
#pragma warning( disable : 4996 ) // disable deprecated warning
#include <strsafe.h>
#pragma warning( default : 4996 )
#include "resource.h"
//=============================================================
//宏定义
#define SAFE_DELETE(p) { if(p) { delete (p); (p)=NULL; } }
#define SAFE_RELEASE(p) { if(p) { (p)->Release(); (p)=NULL; } }
struct XINPUT_DEVICE_NODE
{
DWORD dwVidPid;
XINPUT_DEVICE_NODE* pNext;
};
struct DI_ENUM_CONTEXT
{
DIJOYCONFIG* pPreferredJoyCfg;
bool bPreferredJoyCfgValid;
};
class CDirectInput
{
public:
CDirectInput(void);
public:
~CDirectInput(void);
public:
static LPDIRECTINPUT8 g_pDI;
static LPDIRECTINPUTDEVICE8 g_pJoystick ;
static bool g_bFilterOutXinputDevices;
static XINPUT_DEVICE_NODE* g_pXInputDeviceList;
static DIJOYSTATE2 HandState;
public:
static BOOL CALLBACK EnumObjectsCallback( const DIDEVICEOBJECTINSTANCE* pdidoi, VOID* pContext );
static BOOL CALLBACK EnumJoysticksCallback( const DIDEVICEINSTANCE* pdidInstance, VOID* pContext );
static HRESULT InitDirectInput(HWND hDlg);
static VOID FreeDirectInput();
static DIJOYSTATE2 GetState_Now();
// Stuff to filter out XInput devices
static HRESULT SetupForIsXInputDevice();
static bool IsXInputDevice( const GUID* pGuidProductFromDirectInput );
static void CleanupForIsXInputDevice();
};
//********************************************************************
// DirectInput.h 文件
//********************************************************************************
#include "StdAfx.h"
#include "DirectInput.h"
LPDIRECTINPUT8 CDirectInput::g_pDI = NULL;
LPDIRECTINPUTDEVICE8 CDirectInput::g_pJoystick = NULL;
bool CDirectInput::g_bFilterOutXinputDevices = false;
XINPUT_DEVICE_NODE* CDirectInput::g_pXInputDeviceList = NULL;
DIJOYSTATE2 CDirectInput::HandState;
CDirectInput::CDirectInput(void)
{
}
CDirectInput::~CDirectInput(void)
{
}
//-----------------------------------------------------------------------------
// Name: InitDirectInput()
// Desc: Initialize the DirectInput variables.
//-----------------------------------------------------------------------------
HRESULT CDirectInput::InitDirectInput( HWND hDlg )
{
HRESULT hr;
//创建主com接口
if( FAILED( hr = DirectInput8Create( GetModuleHandle(NULL), /
DIRECTINPUT_VERSION,IID_IDirectInput8,/
(VOID**)&g_pDI, NULL ) ) )
{
return hr;
}
//hr->
if( g_bFilterOutXinputDevices )
SetupForIsXInputDevice();
DIJOYCONFIG PreferredJoyCfg = {0};
DI_ENUM_CONTEXT enumContext;
enumContext.pPreferredJoyCfg = &PreferredJoyCfg;
enumContext.bPreferredJoyCfgValid = false;
IDirectInputJoyConfig8* pJoyConfig = NULL;
if( FAILED( hr = g_pDI->QueryInterface( IID_IDirectInputJoyConfig8, (void **) &pJoyConfig ) ) )
return hr;
PreferredJoyCfg.dwSize = sizeof(PreferredJoyCfg);
if( SUCCEEDED( pJoyConfig->GetConfig(0, &PreferredJoyCfg, DIJC_GUIDINSTANCE ) ) ) // This function is expected to fail if no Joystick is attached
enumContext.bPreferredJoyCfgValid = true;
SAFE_RELEASE( pJoyConfig );
if( FAILED( hr = g_pDI->EnumDevices( DI8DEVCLASS_GAMECTRL,
EnumJoysticksCallback,
&enumContext, DIEDFL_ATTACHEDONLY ) ) )
return hr;
if( g_bFilterOutXinputDevices )
CleanupForIsXInputDevice();
if( NULL == g_pJoystick )
{
/*::MessageBox( NULL, TEXT("Joystick not found. The sample will now exit."),
TEXT("DirectInput Sample"),
MB_ICONERROR | MB_OK );*/
// EndDialog( hDlg, 0 );
return 0-1;
}
if( FAILED( hr = g_pJoystick->SetDataFormat( &c_dfDIJoystick2 ) ) )
return hr;
if( FAILED( hr = g_pJoystick->SetCooperativeLevel( hDlg, DISCL_EXCLUSIVE |
DISCL_FOREGROUND ) ) )
return hr;
if( FAILED( hr = g_pJoystick->EnumObjects( EnumObjectsCallback,
(VOID*)hDlg, DIDFT_ALL ) ) )
return hr;
CDirectInput::GetState_Now();
return S_OK;
}
//-----------------------------------------------------------------------------
// Enum each PNP device using WMI and check each device ID to see if it contains
// "IG_" (ex. "VID_045E&PID_028E&IG_00"). If it does, then it抯an XInput device
// Unfortunately this information can not be found by just using DirectInput.
// Checking against a VID/PID of 0x028E/0x045E won't find 3rd party or future
// XInput devices.
//
// This function stores the list of xinput devices in a linked list
// at g_pXInputDeviceList, and IsXInputDevice() searchs that linked list
//-----------------------------------------------------------------------------
HRESULT CDirectInput::SetupForIsXInputDevice()
{
IWbemServices* pIWbemServices = NULL;
IEnumWbemClassObject* pEnumDevices = NULL;
IWbemLocator* pIWbemLocator = NULL;
IWbemClassObject* pDevices[20] = {0};
BSTR bstrDeviceID = NULL;
BSTR bstrClassName = NULL;
BSTR bstrNamespace = NULL;
DWORD uReturned = 0;
bool bCleanupCOM = false;
UINT iDevice = 0;
VARIANT var;
HRESULT hr;
// CoInit if needed
hr = CoInitialize(NULL);
bCleanupCOM = SUCCEEDED(hr);
// Create WMI
hr = CoCreateInstance( __uuidof(WbemLocator),
NULL,
CLSCTX_INPROC_SERVER,
__uuidof(IWbemLocator),
(LPVOID*) &pIWbemLocator);
if( FAILED(hr) || pIWbemLocator == NULL )
goto LCleanup;
// Create BSTRs for WMI
bstrNamespace = SysAllocString( L"////.//root//cimv2" ); if( bstrNamespace == NULL ) goto LCleanup;
bstrDeviceID = SysAllocString( L"DeviceID" ); if( bstrDeviceID == NULL ) goto LCleanup;
bstrClassName = SysAllocString( L"Win32_PNPEntity" ); if( bstrClassName == NULL ) goto LCleanup;
// Connect to WMI
hr = pIWbemLocator->ConnectServer( bstrNamespace, NULL, NULL, 0L,
0L, NULL, NULL, &pIWbemServices );
if( FAILED(hr) || pIWbemServices == NULL )
goto LCleanup;
// Switch security level to IMPERSONATE
CoSetProxyBlanket( pIWbemServices, RPC_C_AUTHN_WINNT, RPC_C_AUTHZ_NONE, NULL,
RPC_C_AUTHN_LEVEL_CALL, RPC_C_IMP_LEVEL_IMPERSONATE, NULL, 0 );
// Get list of Win32_PNPEntity devices
hr = pIWbemServices->CreateInstanceEnum( bstrClassName, 0, NULL, &pEnumDevices );
if( FAILED(hr) || pEnumDevices == NULL )
goto LCleanup;
// Loop over all devices
for( ;; )
{
// Get 20 at a time
hr = pEnumDevices->Next( 10000, 20, pDevices, &uReturned );
if( FAILED(hr) )
goto LCleanup;
if( uReturned == 0 )
break;
for( iDevice=0; iDevice<uReturned; iDevice++ )
{
// For each device, get its device ID
hr = pDevices[iDevice]->Get( bstrDeviceID, 0L, &var, NULL, NULL );
if( SUCCEEDED( hr ) && var.vt == VT_BSTR && var.bstrVal != NULL )
{
// Check if the device ID contains "IG_". If it does, then it抯an XInput device
// Unfortunately this information can not be found by just using DirectInput
if( wcsstr( var.bstrVal, L"IG_" ) )
{
// If it does, then get the VID/PID from var.bstrVal
DWORD dwPid = 0, dwVid = 0;
WCHAR* strVid = wcsstr( var.bstrVal, L"VID_" );
if( strVid && swscanf( strVid, L"VID_%4X", &dwVid ) != 1 )
dwVid = 0;
WCHAR* strPid = wcsstr( var.bstrVal, L"PID_" );
if( strPid && swscanf( strPid, L"PID_%4X", &dwPid ) != 1 )
dwPid = 0;
DWORD dwVidPid = MAKELONG( dwVid, dwPid );
// Add the VID/PID to a linked list
XINPUT_DEVICE_NODE* pNewNode = new XINPUT_DEVICE_NODE;
if( pNewNode )
{
pNewNode->dwVidPid = dwVidPid;
pNewNode->pNext = g_pXInputDeviceList;
g_pXInputDeviceList = pNewNode;
}
}
}
SAFE_RELEASE( pDevices[iDevice] );
}
}
LCleanup:
if(bstrNamespace)
SysFreeString(bstrNamespace);
if(bstrDeviceID)
SysFreeString(bstrDeviceID);
if(bstrClassName)
SysFreeString(bstrClassName);
for( iDevice=0; iDevice<20; iDevice++ )
SAFE_RELEASE( pDevices[iDevice] );
SAFE_RELEASE( pEnumDevices );
SAFE_RELEASE( pIWbemLocator );
SAFE_RELEASE( pIWbemServices );
return hr;
}
//-----------------------------------------------------------------------------
// Returns true if the DirectInput device is also an XInput device.
// Call SetupForIsXInputDevice() before, and CleanupForIsXInputDevice() after
//-----------------------------------------------------------------------------
bool CDirectInput::IsXInputDevice( const GUID* pGuidProductFromDirectInput )
{
// Check each xinput device to see if this device's vid/pid matches
XINPUT_DEVICE_NODE* pNode = g_pXInputDeviceList;
while( pNode )
{
if( pNode->dwVidPid == pGuidProductFromDirectInput->Data1 )
return true;
pNode = pNode->pNext;
}
return false;
}
//-----------------------------------------------------------------------------
// Cleanup needed for IsXInputDevice()
//-----------------------------------------------------------------------------
void CDirectInput::CleanupForIsXInputDevice()
{
// Cleanup linked list
XINPUT_DEVICE_NODE* pNode = g_pXInputDeviceList;
while( pNode )
{
XINPUT_DEVICE_NODE* pDelete = pNode;
pNode = pNode->pNext;
SAFE_DELETE( pDelete );
}
}
//-----------------------------------------------------------------------------
// Name: EnumJoysticksCallback()
// Desc: Called once for each enumerated Joystick. If we find one, create a
// device interface on it so we can play with it.
//-----------------------------------------------------------------------------
BOOL CALLBACK CDirectInput::EnumJoysticksCallback( const DIDEVICEINSTANCE* pdidInstance,
VOID* pContext )
{
DI_ENUM_CONTEXT* pEnumContext = (DI_ENUM_CONTEXT*) pContext;
HRESULT hr;
if( g_bFilterOutXinputDevices && IsXInputDevice( &pdidInstance->guidProduct ) )
return DIENUM_CONTINUE;
// Skip anything other than the perferred Joystick device as defined by the control panel.
// Instead you could store all the enumerated Joysticks and let the user pick.
if( pEnumContext->bPreferredJoyCfgValid &&
!IsEqualGUID( pdidInstance->guidInstance, pEnumContext->pPreferredJoyCfg->guidInstance ) )
return DIENUM_CONTINUE;
// Obtain an interface to the enumerated Joystick.
hr = g_pDI->CreateDevice( pdidInstance->guidInstance, &g_pJoystick, NULL );
// If it failed, then we can't use this Joystick. (Maybe the user unplugged
// it while we were in the middle of enumerating it.)
if( FAILED(hr) )
return DIENUM_CONTINUE;
// Stop enumeration. Note: we're just taking the first Joystick we get. You
// could store all the enumerated Joysticks and let the user pick.
return DIENUM_STOP;
}
//-----------------------------------------------------------------------------
// Name: EnumObjectsCallback()
// Desc: Callback function for enumerating objects (axes, buttons, POVs) on a
// Joystick. This function enables user interface elements for objects
// that are found to exist, and scales axes min/max values.
//-----------------------------------------------------------------------------
BOOL CALLBACK CDirectInput::EnumObjectsCallback( const DIDEVICEOBJECTINSTANCE* pdidoi,
VOID* pContext )
{
HWND hDlg = (HWND)pContext;
static int nSliderCount = 0; // Number of returned slider controls
static int nPOVCount = 0; // Number of returned POV controls
// For axes that are returned, set the DIPROP_RANGE property for the
// enumerated axis in order to scale min/max values.
if( pdidoi->dwType & DIDFT_AXIS )
{
DIPROPRANGE diprg;
diprg.diph.dwSize = sizeof(DIPROPRANGE);
diprg.diph.dwHeaderSize = sizeof(DIPROPHEADER);
diprg.diph.dwHow = DIPH_BYID;
diprg.diph.dwObj = pdidoi->dwType; // Specify the enumerated axis
diprg.lMin = -1000;
diprg.lMax = +1000;
// Set the range for the axis
if( FAILED( g_pJoystick->SetProperty( DIPROP_RANGE, &diprg.diph ) ) )
return DIENUM_STOP;
}
return DIENUM_CONTINUE;
}
//-----------------------------------------------------------------------------
// Name: UpdateInputState()
// Desc: Get the input device's state and display it.
//-----------------------------------------------------------------------------
DIJOYSTATE2 CDirectInput::GetState_Now()
{
HRESULT hr;
DIJOYSTATE2 js; // DInput Joystick state
hr = g_pJoystick->Poll();
if( FAILED(hr) )
{
hr = g_pJoystick->Acquire();
while( hr == DIERR_INPUTLOST )
hr = g_pJoystick->Acquire();
//return S_OK;
}
// Get the input's device state
if( FAILED( hr = g_pJoystick->GetDeviceState( sizeof(DIJOYSTATE2), &js ) ) );
// CString str;
//str.Format("%d",js.lX);
CDirectInput::HandState = js;
return js;
//AfxMessageBox(str);
}
//-----------------------------------------------------------------------------
// Name: FreeDirectInput()
// Desc: Initialize the DirectInput variables.
//-----------------------------------------------------------------------------
VOID CDirectInput::FreeDirectInput()
{
// Unacquire the device one last time just in case
// the app tried to exit while the device is still acquired.
if( g_pJoystick )
g_pJoystick->Unacquire();
// Release any DirectInput objects.
SAFE_RELEASE( g_pJoystick );
SAFE_RELEASE( g_pDI );
}
- USB手柄的控制
- WinCE下的USB游戏手柄驱动 GamePad Joystick
- unity开发 HTC vive手柄控制 手柄上各个按钮的点击事件
- Unity3d开发 HTC vive手柄控制 手柄上各个按钮的点击事件
- iOS游戏控制手柄
- Android手柄焦点控制
- 手柄控制-XInputDotNet插件
- arduino读取控制手柄
- ubuntu下使用USB手柄
- 与Wii控制手柄通信的托管代码库(一)
- 与Wii控制手柄通信的托管代码库(二)
- VR开发中HTC的手柄控制按键设置(1)
- VR开发中HTC手柄发射射线的控制
- android手机使用otg usb手柄
- 使用C#+socket实现用移动设备控制的虚拟手柄
- 游戏手柄(JoyStick)编程控制的一个简单代码(Qt)
- 手机模拟蓝牙手柄控制kobuki底座
- 使用北通手柄控制turtlesim运动
- Win2003下的事情
- 参加第二届csdn技术英雄大会的一点感受
- Linux下C程序命令行参数处理
- Java实现的拦截器模型
- 网页标准化-CSS命名规划整理
- USB手柄的控制
- Ogre图形引擎介绍
- ASP随机函数,四位随机数
- 位运算 与逻辑运算 总结!
- 无边框窗体的移动方法
- 我的论坛www.cmmisoft.com
- Teach Yourself Programming in Ten Years
- trace
- 屏幕抓屏(包括活动窗口,指定区域及全屏等)