/*------------------------------------------------------------
DirectInput サンプルプログラム
2007 Copyright(C) Toru
ToruのDirectXプログラミング講座
URL : http://toruweb.web.fc2.com/
Mail : toru_website@hotmail.com
--------------------------------------------------------------*/
#define STRICT
// インクルード
#include
#include
#include
// インターフェイス解放
#define RELEASE(x) {if(x){(x)->Release();x=NULL;}}
// アプリケーション情報
HINSTANCE g_hInst; // インスタンスハンドル
HWND g_hWnd; // ウインドウハンドル
CHAR g_szAppName[] = "DirectInput Sample"; // アプリケーション名
BOOL g_bActive = TRUE; // ウインドウのアクティブ状態
// DirectInputの変数
LPDIRECTINPUT8 g_lpDI = NULL; // DirectInput
LPDIRECTINPUTDEVICE8 g_lpDIDevice = NULL; // DirectInputデバイス
DIDEVCAPS g_diDevCaps; // ジョイスティックの能力
// メッセージ関数の定義
LRESULT CALLBACK MainWndProc( HWND hWnd, UINT msg, UINT wParam, LONG lParam );
// DirectInputコールバック関数
BOOL CALLBACK EnumJoysticksCallback( const DIDEVICEINSTANCE* lpddi, LPVOID lpContext );
BOOL CALLBACK EnumAxesCallback( LPCDIDEVICEOBJECTINSTANCE lpddoi, LPVOID lpvRef );
// アプリケーションの初期化
BOOL InitApp( HINSTANCE hInst, INT nCmdShow )
{
// インスタンスハンドル保存
g_hInst = hInst;
// ウインドウクラスの登録
WNDCLASS wc;
ZeroMemory( &wc, sizeof(wc) );
wc.hCursor = LoadCursor( NULL, IDC_ARROW );
wc.lpszClassName = "Main Window";
wc.hbrBackground = (HBRUSH)GetStockObject( WHITE_BRUSH );
wc.hInstance = hInst;
wc.style = CS_BYTEALIGNCLIENT | CS_VREDRAW|CS_HREDRAW;
wc.lpfnWndProc = (WNDPROC)MainWndProc;
if( ! RegisterClass(&wc) )
{
DXTRACE_MSG( "ウインドウクラスの登録に失敗" );
return FALSE;
}
// メインウインドウの作成
g_hWnd = CreateWindowEx( 0, "Main Window", g_szAppName,
WS_OVERLAPPED | WS_SYSMENU | WS_CAPTION,
CW_USEDEFAULT, CW_USEDEFAULT, 320, 240,
(HWND)NULL, (HMENU)NULL, hInst, (LPSTR)NULL);
if( g_hWnd == NULL )
{
DXTRACE_MSG( "メインウインドウ作成に失敗" );
return FALSE;
}
// メインウインドウの表示
ShowWindow( g_hWnd, nCmdShow );
UpdateWindow( g_hWnd );
return TRUE;
}
// DirectInput 初期化
BOOL InitDInput()
{
HRESULT hr;
// DirectInputの作成
hr = DirectInput8Create( g_hInst, DIRECTINPUT_VERSION, IID_IDirectInput8, (LPVOID*)&g_lpDI, NULL );
if( FAILED(hr) )
{
DXTRACE_ERR( "DirectInput8オブジェクトの作成に失敗", hr );
return FALSE;
}
// デバイスを列挙して作成
hr = g_lpDI->EnumDevices( DI8DEVCLASS_GAMECTRL, EnumJoysticksCallback, NULL, DIEDFL_ATTACHEDONLY );
if( FAILED(hr) || g_lpDIDevice==NULL )
{
DXTRACE_ERR( "DirectInputDevice8オブジェクトの作成に失敗", hr );
return FALSE;
}
// データ形式を設定
hr = g_lpDIDevice->SetDataFormat( &c_dfDIJoystick );
if( FAILED(hr) )
{
DXTRACE_ERR( "c_dfDIJoystick2形式の設定に失敗", hr );
return FALSE;
}
// モードを設定(フォアグラウンド&非排他モード)
hr = g_lpDIDevice->SetCooperativeLevel( g_hWnd, DISCL_FOREGROUND | DISCL_NONEXCLUSIVE );
if( FAILED(hr) )
{
DXTRACE_ERR( "フォアグラウンド&非排他モードの設定に失敗", hr );
return FALSE;
}
// コールバック関数を使って各軸のモードを設定
hr = g_lpDIDevice->EnumObjects( EnumAxesCallback, NULL, DIDFT_AXIS );
if( FAILED(hr) )
{
DXTRACE_ERR( "軸モードの設定に失敗", hr );
return FALSE;
}
// 軸モードを設定
DIPROPDWORD diprop;
diprop.diph.dwSize = sizeof(diprop);
diprop.diph.dwHeaderSize = sizeof(diprop.diph);
diprop.diph.dwObj = 0;
diprop.diph.dwHow = DIPH_DEVICE;
diprop.dwData = DIPROPAXISMODE_ABS; // 絶対値モード
// diprop.dwData = DIPROPAXISMODE_REL; // 相対値モード
hr = g_lpDIDevice->SetProperty( DIPROP_AXISMODE, &diprop.diph );
if( FAILED(hr) )
{
DXTRACE_ERR( "軸モードの設定に失敗", hr );
return FALSE;
}
// 入力制御開始
g_lpDIDevice->Acquire();
return TRUE;
}
// ジョイスティックを列挙する関数
BOOL CALLBACK EnumJoysticksCallback( const DIDEVICEINSTANCE* lpddi, LPVOID lpContext )
{
HRESULT hr;
// 列挙されたジョイスティックへのインターフェイスを取得する。
hr = g_lpDI->CreateDevice( lpddi->guidInstance, &g_lpDIDevice, NULL );
if( FAILED(hr) ) return DIENUM_CONTINUE;
// ジョイスティックの能力を調べる
g_diDevCaps.dwSize = sizeof(DIDEVCAPS);
hr = g_lpDIDevice->GetCapabilities( &g_diDevCaps );
if( FAILED(hr) )
{
// ジョイスティック能力の取得に失敗
RELEASE( g_lpDIDevice );
return DIENUM_CONTINUE;
}
return DIENUM_STOP;
}
// ジョイスティックの軸を列挙する関数
BOOL CALLBACK EnumAxesCallback( LPCDIDEVICEOBJECTINSTANCE lpddoi, LPVOID lpvRef )
{
HRESULT hr;
// 軸の値の範囲を設定(-1000~1000)
DIPROPRANGE diprg;
ZeroMemory(&diprg, sizeof(diprg));
diprg.diph.dwSize = sizeof(diprg);
diprg.diph.dwHeaderSize = sizeof(diprg.diph);
diprg.diph.dwObj = lpddoi->dwType;
diprg.diph.dwHow = DIPH_BYID;
diprg.lMin = -1000;
diprg.lMax = +1000;
hr = g_lpDIDevice->SetProperty( DIPROP_RANGE, &diprg.diph );
if( FAILED(hr) ) return DIENUM_STOP;
return DIENUM_CONTINUE;
}
// DirectInputの解放処理
BOOL ReleaseDInput()
{
// DirectInputのデバイスを解放
if( g_lpDIDevice ) g_lpDIDevice->Unacquire();
RELEASE(g_lpDIDevice);
RELEASE(g_lpDI);
return TRUE;
}
// 終了の処理
BOOL EndApp()
{
return TRUE;
}
// ウインドウの描画処理
void WM_Paint( HWND hWnd )
{
PAINTSTRUCT ps;
HDC hDC = BeginPaint( hWnd, &ps );
// デバイスが存在すれば
if( g_lpDIDevice!=NULL )
{
CHAR szStr[1024];
HRESULT hr;
// デバイスの直接データを取得する
hr = g_lpDIDevice->Poll();
if( FAILED(hr) )
{
hr = g_lpDIDevice->Acquire();
while( g_bActive && hr==DIERR_INPUTLOST )
{
hr = g_lpDIDevice->Acquire();
}
}
DIJOYSTATE dijs;
hr = g_lpDIDevice->GetDeviceState( sizeof(DIJOYSTATE), &dijs );
if( SUCCEEDED(hr) )
{
// 軸表示
wsprintf( szStr,"X=%d Y=%d Z=%d", dijs.lX, dijs.lY, dijs.lZ );
TextOut( hDC, 0, 0, szStr, lstrlen(szStr) );
// ボタン表示
int nStrSize = 0;
for( int i=0; i<8; i++ )
{
if( dijs.rgbButtons[i] & 0x80 ) nStrSize += wsprintf( szStr + nStrSize,"%d", i );
else nStrSize += wsprintf( szStr + nStrSize,"-" );
}
szStr[nStrSize] = 0;
TextOut( hDC, 0, 20, szStr, lstrlen(szStr) );
}
// エラー
else if( g_bActive && hr==DIERR_INPUTLOST )
{
// アクセス権の再取得
g_lpDIDevice->Acquire();
}
}
EndPaint(hWnd, &ps);
}
// ウインドウ処理
LRESULT CALLBACK MainWndProc( HWND hWnd, UINT msg, UINT wParam, LONG lParam )
{
switch(msg)
{
// ウインドウのアクティブ状態が変化
case WM_ACTIVATE:
if(g_lpDIDevice == NULL) break;
g_bActive = wParam != WA_INACTIVE;
if( wParam == WA_INACTIVE ) g_lpDIDevice->Unacquire();
else g_lpDIDevice->Acquire();
break;
// ウインドウが作られた
case WM_CREATE:
SetTimer(hWnd, 1, 100, NULL);
break;
// ウインドウが破棄される
case WM_DESTROY:
KillTimer(hWnd, 1);
PostQuitMessage(0);
break;
// タイマーイベント発生
case WM_TIMER:
// 画面更新
InvalidateRect(hWnd, NULL, TRUE);
break;
// 画面描画
case WM_PAINT:
WM_Paint(hWnd);
break;
// その他のメッセージ
default:
return DefWindowProc(hWnd,msg,wParam,lParam);
}
return 0L;
}
// メイン
int WINAPI WinMain( HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR lpCmdLine, int nCmdShow )
{
MSG msg;
// アプリケーションの初期化
if( InitApp( hInst, nCmdShow ) )
{
// DirecInputの初期化
if( InitDInput() )
{
// メッセージループ
while( GetMessage( &msg, 0, 0, 0 ) )
{
if( msg.message == WM_QUIT ) break;
TranslateMessage( &msg );
DispatchMessage( &msg );
}
}
}
// DirectInputの終了処理
ReleaseDInput();
// アプリケーションの終了処理
EndApp();
return msg.wParam;
}
- Last Update 2007/1/21
- Copyright © 2002-2007 Toru. All Rights Reserved.
- toru_website@hotmail.com