ホーム > サンプルプログラム > 直接データでジョイスティックの状態を取得

/*------------------------------------------------------------
    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;
}


inserted by FC2 system