[ create a new paste ] login | about

Link: http://codepad.org/w76XAEDd    [ raw code | fork ]

Plain Text, pasted on Jan 18:
// -------------------------------------------------------------- joy_ctrl.h
#ifndef _JOYSTICK_CTRL_H_
#define _JOYSTICK_CTRL_H_

#include <windows.h>

/**
 * JoyStick(JoyPad) コントロールクラス(PImpl) by ミングスレの名無し
 * 
 * 使用方法:
 *  WinMain 内で親ウィンドウのハンドル渡して
 *   start で放置。以後、内部の別スレッドがJoyPadを監視して
 *   WM_KEYDOWN を飛ばす。十字キーでカーソルキーのコードを飛ばす(VK_XXX)
 *   しかし現在エラい事になるので改修必須
 */
class JoyStick {
private:
	void *pjc;
public:
	JoyStick(HWND hWnd);
	~JoyStick();

	// 監視とメッセージ送信のスレッド開始
	void start();
};

#endif



// -------------------------------------------------------------- joy_ctrl.cpp
#include "joy_ctrl.h"

#define DIRECTINPUT_VERSION 0x0800
#ifndef _WIN32_DCOM
#define _WIN32_DCOM
#endif

#pragma comment(lib, "dxguid.lib")
#pragma comment(lib, "dinput8.lib")

#include <dinput.h>
#include <dinputd.h>

#include <boost/thread.hpp>
#include <boost/function.hpp>

#define SAFE_DELETE(p) { if(p) { delete (p); (p)=NULL; } }
#define SAFE_RELEASE(p) { if(p) { (p)->Release(); (p)=NULL; } }

BOOL CALLBACK enumObjCallback( const DIDEVICEOBJECTINSTANCE* pdidoi, VOID* pContext );
BOOL CALLBACK enumJSCallback( const DIDEVICEINSTANCE* pdidInstance, VOID* pContext );

// --------------------------------------------------------------------------------
// --
struct DI_ENUM_CONTEXT
{
    DIJOYCONFIG* pJoyCfg;
    bool bJoyCfgValid;

	LPDIRECTINPUT8 *g_pDI;
	LPDIRECTINPUTDEVICE8 *g_pJoystick;
};

// --------------------------------------------------------------------------------
// --
class _P_JoyCtrl {
private:
	typedef boost::mutex::scoped_lock lock;
	boost::mutex mtx;
	boost::thread *th;
	boost::condition_variable_any cond;

	HWND hWnd;
	HRESULT hr;
	volatile bool bLoop;

	LPDIRECTINPUT8 g_pDI;
	LPDIRECTINPUTDEVICE8 g_pJoystick;

	HRESULT init_dinput();
	HRESULT send_dinput_state();
	void free_dinput();

	void thread_run();
public:
	_P_JoyCtrl(HWND);
	~_P_JoyCtrl();
	void stop();
	void start();
};

// --------------------------------------------------------------------------------
// --
_P_JoyCtrl::_P_JoyCtrl(HWND hTarget)
	: th(NULL), g_pDI(NULL), g_pJoystick(NULL)
{
	hWnd = hTarget;
	hr = init_dinput();
}

_P_JoyCtrl::~_P_JoyCtrl()
{
	stop();
	th->join();
	delete th;
	free_dinput();
}

void _P_JoyCtrl::start()
{
	if(FAILED(hr)) throw std::runtime_error("error: can't start");
	if(th != NULL) return;

	bLoop = true;
	boost::function<void (void)> f = boost::bind(&_P_JoyCtrl::thread_run, this);
	th = new boost::thread(f);
}

void _P_JoyCtrl::stop()
{
	lock l(mtx);
	bLoop = false;
	cond.notify_one();
}

void _P_JoyCtrl::thread_run()
{
	while(bLoop)
	{
		lock l(mtx);

		if(FAILED(hr = send_dinput_state()))
		{
			bLoop = false;
			break;
		}

		boost::xtime t;
		boost::xtime_get(&t, boost::TIME_UTC);
		t.nsec += 1000*300;

		if(cond.timed_wait(l, t)) break;
	}
}

HRESULT _P_JoyCtrl::init_dinput()
{
    IDirectInputJoyConfig8* pJoyConfig = NULL;
	if(
		FAILED(hr = DirectInput8Create(
			(HINSTANCE)GetWindowLong(hWnd, GWL_HINSTANCE),
			DIRECTINPUT_VERSION,
			IID_IDirectInput8, ( VOID** )&g_pDI, NULL
		))
		|| FAILED(hr = g_pDI->QueryInterface( IID_IDirectInputJoyConfig8, (void**)&pJoyConfig ))
	) return hr;

    DIJOYCONFIG prefConf = {0};

    DI_ENUM_CONTEXT enCon;
    enCon.pJoyCfg = &prefConf;
    enCon.bJoyCfgValid = false;
	enCon.g_pDI = &g_pDI;
	enCon.g_pJoystick = &g_pJoystick;

	prefConf.dwSize = sizeof( prefConf );
    if(SUCCEEDED(pJoyConfig->GetConfig(0, &prefConf, DIJC_GUIDINSTANCE) )) enCon.bJoyCfgValid = true;
	SAFE_RELEASE( pJoyConfig );

    if(FAILED(
		hr = g_pDI->EnumDevices(DI8DEVCLASS_GAMECTRL, enumJSCallback, &enCon, DIEDFL_ATTACHEDONLY)
	)) return hr;

	hr = E_FAIL;
    if(
		NULL == g_pJoystick
		|| FAILED( hr = g_pJoystick->SetDataFormat( &c_dfDIJoystick2 ) )
		|| FAILED( hr = g_pJoystick->SetCooperativeLevel( hWnd, DISCL_EXCLUSIVE | DISCL_FOREGROUND ) )
		|| FAILED( hr = g_pJoystick->EnumObjects( enumObjCallback, &enCon, DIDFT_ALL ) )
	) return hr;

    return S_OK;
}

HRESULT _P_JoyCtrl::send_dinput_state()
{
    if( NULL == g_pJoystick ) return S_OK;

    if(FAILED(hr = g_pJoystick->Poll()))
    {
        hr = g_pJoystick->Acquire();
        while( hr == DIERR_INPUTLOST ) hr = g_pJoystick->Acquire();
        return S_OK;
    }

    DIJOYSTATE2 js;
    if(
		FAILED(hr = g_pJoystick->GetDeviceState(sizeof(DIJOYSTATE2), &js))
	) return hr;

	// URLB
	// 0001
	//const char KEYCHAR[] = {'0','2','4','1',  '6','3','0','0',  '8','0','7','0',  '9','0','0','0'};
	const char KEYCHAR[] = {
		'0'
		, VK_DOWN
		, VK_LEFT
		, VK_DOWN | VK_LEFT	// TODO: ダメ、そうじゃない
		, VK_RIGHT
		, VK_RIGHT | VK_DOWN
		,'0','0'
		, VK_UP
		,'0'
		, VK_UP | VK_LEFT
		,'0'
		, VK_UP | VK_RIGHT
		,'0','0','0'
	};
	const char BTNCHAR[] = {'A','B','C','D','E',  'F','G','H','I','J'};

	BYTE blg = 0;

	if(js.lX < LONG(-10)) blg |= 2;
	else if(js.lX > LONG(10)) blg |= 4;

	if(js.lY < LONG(-10)) blg |= 8;
	else if(js.lY > LONG(10)) blg |= 1;

	//if(blg) SendMessage(hWnd, WM_CHAR, WPARAM(KEYCHAR[blg]), LPARAM(0));
	if(blg) SendMessage(hWnd, WM_KEYDOWN, WPARAM(KEYCHAR[blg]), LPARAM(0));

    for(int i=0, ln=sizeof(BTNCHAR)/sizeof(char); i<ln; i++)	// ln=128
    {
        if( js.rgbButtons[i] & 0x80 )
        {
			SendMessage(hWnd, WM_CHAR, WPARAM(BTNCHAR[i]), LPARAM(0));	// 'A'+i
        }
    }

	return S_OK;
}

void _P_JoyCtrl::free_dinput()
{
    if( g_pJoystick ) g_pJoystick->Unacquire();

    SAFE_RELEASE( g_pJoystick );
    SAFE_RELEASE( g_pDI );
}

// --------------------------------------------------------------------------------
// --
BOOL CALLBACK enumJSCallback(
	const DIDEVICEINSTANCE* pDDev, void* pAny
) {
    DI_ENUM_CONTEXT* pEnCon = (DI_ENUM_CONTEXT*)pAny;
    if(
		pEnCon->bJoyCfgValid
		&& !IsEqualGUID(pDDev->guidInstance, pEnCon->pJoyCfg->guidInstance)
	) return DIENUM_CONTINUE;

    HRESULT hr;
    if(FAILED(
		hr = (*(pEnCon->g_pDI))->CreateDevice( pDDev->guidInstance, pEnCon->g_pJoystick, NULL )
	)) return DIENUM_CONTINUE;

	return DIENUM_STOP;
}

BOOL CALLBACK enumObjCallback(
	const DIDEVICEOBJECTINSTANCE* pdidoi, void* pAny
){
    DI_ENUM_CONTEXT* pEnCon = (DI_ENUM_CONTEXT*)pAny;

	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;
        diprg.lMin = -1000;
        diprg.lMax = +1000;

		if( FAILED( (*(pEnCon->g_pJoystick))->SetProperty( DIPROP_RANGE, &diprg.diph ) ) ) return DIENUM_STOP;
    }

	static unsigned int FLG = 0;	// TODO: 現在放置
    if( pdidoi->guidType == GUID_XAxis ) FLG |= 1;
    if( pdidoi->guidType == GUID_YAxis ) FLG |= 2;
    if( pdidoi->guidType == GUID_ZAxis ) FLG |= 4;
    if( pdidoi->guidType == GUID_RxAxis ) FLG |= 8;
    if( pdidoi->guidType == GUID_RyAxis ) FLG |= 16;
    if( pdidoi->guidType == GUID_RzAxis ) FLG |= 32;

    return DIENUM_CONTINUE;
}

// --------------------------------------------------------------------------------
// --
JoyStick::JoyStick(HWND hWnd)
{
	pjc = new _P_JoyCtrl(hWnd);
}

JoyStick::~JoyStick()
{
	delete reinterpret_cast<_P_JoyCtrl*>(pjc);
}

void JoyStick::start()
{
	reinterpret_cast<_P_JoyCtrl*>(pjc)->start();
}




Create a new paste based on this one


Comments: