DirectInputでのエラー

このQ&Aのポイント
  • DirectInputを使用してゲームコントローラーを列挙するためのコードでエラーが発生しています。
  • msdnやDirectXSDKのサンプルを参考にしたコードで、特定のエラーメッセージが表示されます。
  • エラーメッセージは引数の型変換に関するものであり、解決策が見つかっていません。
回答を見る
  • ベストアンサー

DirectInput でのエラー

LPDIRECTINPUT8 m_pDI; LPDIRECTINPUTDEVICE8 m_pJoystick; 省略 // ゲームコントローラーの列挙 if(FAILED(hr = m_pDI->EnumDevices(DI8DEVCLASS_GAMECTRL, EnumJoysticksCalback, NULL, DIEDFL_ATTACHEDONLY))) return hr; //********************************************************/ BOOL CALLBACK InputDevice::EnumJoysticksCallback(const DIDEVICEINSTANCE* pdidInstance, VOID* pContext ) { HRESULT hr; hr = m_pDI->CreateDevice(pdidInstance->guidInstance, &m_pJoystick, NULL); if(FAILED(hr)){ return DIENUM_CONTINUE; }else{ return DIENUM_STOP; } } ゲームコントローラーの列挙をするためのコードを msdn や DirectXSDK のサンプルを 参考に書きました。でもどうしても以下のようなエラーがでます。 キャストなど試してみましたが解決にはいたりませんでした。 どうかご教授おねがいします。 d:\○○△△.cpp(30) : error C2664: 'IDirectInput8A::EnumDevices' : 2 番目の引数を 'BOOL (const DIDEVICEINSTANCE *,void *)' から 'LPDIENUMDEVICESCALLBACKA' に変換できません。

  • nVIDIA
  • お礼率46% (520/1121)

質問者が選んだベストアンサー

  • ベストアンサー
  • aho0xff
  • ベストアンサー率12% (218/1772)
回答No.1

お気持ちよーく分かります。 でもとても不便なことに、コールバック関数に通常のクラスメンバ関数は指定できないのですよ。 ひと工夫必要なんです。 解決策は簡単に言えば2つ 完全なグローバル関数として定義 BOOL CALLBACK EnumJoysticksCallback(const DIDEVICEINSTANCE* pdidInstance, VOID* pContext ); 静的なクラスメンバ関数として定義 static BOOL CALLBACK InputDevice::EnumJoysticksCallback(const DIDEVICEINSTANCE* pdidInstance, VOID* pContext ); 要は暗黙に使われている this ポインタが邪魔なのですよ(厳密に言えばだいぶ違いますけど)。 参考URLにそこらへんを書いてるURLを上げておきます。 まあ、何とかエレガント(笑)にしたいところですけどね。 個人的にはこんな感じ(コンパイル通るかどうかまではやりませんが)でやるかな・・・・ // ゲームコントローラーの列挙(3番目の引数にthisをセット(この部分が class InputDevice のメンバ関数の中なら)) if(FAILED(hr = m_pDI->EnumDevices(DI8DEVCLASS_GAMECTRL, EnumJoysticksCalback, this, DIEDFL_ATTACHEDONLY))) return hr; //********************************************************/ // クラスの static 定義の細かい部分は修正してください(たぶん間違ってる??) static BOOL CALLBACK InputDevice::EnumJoysticksCallback(const DIDEVICEINSTANCE* pdidInstance, VOID* pContext ) { HRESULT hr; InputDevice* pObj = ( InputDevice* )pContext;// pContext には先の this のアドレスが入っているはず hr = pObj->m_pDI->CreateDevice(pdidInstance->guidInstance, &pObj->m_pJoystick, NULL); // なのでコレがいける if(FAILED(hr)){ return DIENUM_CONTINUE; }else{ return DIENUM_STOP; } } まあ確かにいちいちこんなことを・・・ってのはありますね。 ちなみにコレDirectInputに限らず、コールバック関数をクラス定義するときには必ず付いて回る問題です。

参考URL:
http://techtips.belution.com/ja/vc/0009/
nVIDIA
質問者

お礼

エラーは外れました!どうもありがとうございます! コールバック関数はテキストにも掲載されていないので、全く0からのスタートでした。 だから、最初から苦戦を予想していましたが、 その予想も的中したようです。 でも、おかげでコールバック関数のクラス化の方法が見えました。改めてありがとうございました。

関連するQ&A

  • コールバック関数とクラスとの間のトラブル

    // クラスの定義 class CInputDevice{ private: LPDIRECTINPUT8 m_pDInput; LPDIRECTINPUTDEVICE8 m_pJoystick; public: HRESULT CreateInput(HWND hWnd); // コールバック関数 static BOOL CALLBACK EnumJoysticksCallback( const DIDEVICEINSTANCE* pdidInstance, VOID* pContext); }; // メンバ関数 HRESULT CInputDevice::CreateInput(HWND hWnd) { 省 略 // ゲームコントローラーの列挙:コールバック関数呼出 if(FAILED(hr = m_pDInput->EnumDevices(DI8DEVCLASS_GAMECTRL,EnumJoysticksCallback, NULL, DIEDFL_ATTACHEDONLY))) return hr; 省 略 return S_OK; } // コールバック関数 BOOL CALLBACK CInputDevice::EnumJoysticksCallback(const DIDEVICEINSTANCE* pdidInstance, VOID* pContext) { HRESULT hr; CInputDevice* pDevice = (CInputDevice*) pContext; // ▼アヤシイ部分 hr = pDevice->m_pDInput->CreateDevice(pdidInstance->guidInstance, &pDevice->m_pJoystick,NULL); if(FAILED(hr)){ return DIENUM_CONTINUE; }else{ return DIENUM_STOP; } } これは下のURLで質問した時のアドバイスを元に修正したものです。 http://oshiete1.goo.ne.jp/kotaeru.php3?q=2305038 おかげでコンパイル時はエラーは出なくなりましたが。。。 実行時メモリに関する警告メッセージが出るようになりました。 そしてデバッガで調べたところ、コールバック関数内で、 どうやらメンバ関数からの値が完全に行き渡っていないようです。 そういえば、 >要は暗黙に使われている this ポインタが邪魔なのですよ と一言書いてあったのですが、これが解決の鍵を持っているのではないかと 思います。試してみましたが返ってエラーが多発するだけで現在STOP状態です。 どうか、ご教授ください。おねがいします!

  • DirectInputについて

    C++でDirectinputの事なのですが。 デバッグには成功するのに、起動した後すぐ強制終了してしまいます。 VOID KeyCheck() { BYTE KeyState[256]; HRESULT hr; hr = g_lpDIDevice->GetDeviceState(256,KeyState); if (SUCCEEDED(hr)) { if (KeyState[DIK_LEFT]&0x80) muki=0; } else hr = g_lpDIDevice->Acquire(); } directxの勉強に簡単なものを書いてみようと思ったのですが、どの辺りがいけないのでしょうか?

  • DirectInputについて再

    前に回答してくださった方すみません。 directinputで、デバックに成功して実行してみるとすぐに強制終了してしまう問題なのですが。 VOID KeyCheck() { BYTE KeyState[256]; HRESULT hr; hr = g_lpDIDevice->GetDeviceState(256,KeyState); if (SUCCEEDED(hr)) { if (KeyState[DIK_LEFT]&0x80) muki=0; } } 強制終了が出なくなったのはこの処理が実行されていなかっただけらしく、まだおかしいみたいなんです。 hr = g_lpDIDevice->GetDeviceState(256,KeyState); この文辺りが怪しいと思って256をsizeof(KeyState)にしたりなどいろいろなサイトで違った方法を試したりなどしたのですが、解決しませんでした。 OSはVistaの32bitなのですが、どのようにすれば治るでしょうか?

  • DirectXを用いたActiveXを用いてVistaで情報が取れない

    ActiveXからDirectXを叩いてOSやCPUなどの情報を 取得しようとしています。 XPでは問題なく情報が取れますが、Vistaでは 情報が取れる項目と取れない項目があります。 この現象について、教えてください。 APIは正常に終了しています。 OS(szOSExLongEnglish) → 正常取得 ベンダー(szSystemManufacturerEnglish) → n/a 型番(szSystemModelEnglish) → n/a CPU(szProcessorEnglish) → (空白) 物理メモリ(szPhysicalMemoryEnglish)  → 正常取得 IEのデフォルトの設定では上記のような状態ですが、 設定を変えて保護モードを外すと正常動作し、 すべての情報が取得できます。 しかし、保護モードが有効の状態で、 情報取得したいです。 以下にコードを書きます。 ※このコードはあるサンプルソースをほとんどそのまま使っています。 //////////////////////////////////////////////////////////////////////////////// // 初期化 //////////////////////////////////////////////////////////////////////////////// bool CDxDiagLib::Init(void) { HRESULT hr; DXDIAG_INIT_PARAMS dxDiagInitParam; m_pDxDiagProvider = NULL; m_pDxDiagRoot = NULL; g_DxDiagInfo = NULL; g_DxSoundInfo = NULL; // COMライブラリを使用できるように初期化 hr = CoInitialize(NULL); if (FAILED(hr)) { return false; } hr = CoCreateInstance( CLSID_DxDiagProvider, NULL, CLSCTX_INPROC_SERVER, IID_IDxDiagProvider, (LPVOID*) &m_pDxDiagProvider); if( FAILED(hr) || m_pDxDiagProvider == NULL) { return false; } // DXDIAG_INIT_PARAMSを初期化 ZeroMemory( &dxDiagInitParam, sizeof(DXDIAG_INIT_PARAMS) ); dxDiagInitParam.dwSize = sizeof(DXDIAG_INIT_PARAMS); dxDiagInitParam.dwDxDiagHeaderVersion = DXDIAG_DX9_SDK_VERSION; // WHQLを確認するかどうか // ネットを経由するので基本的にはfalseにしておく dxDiagInitParam.bAllowWHQLChecks = AllowWHQLChecks; dxDiagInitParam.pReserved = NULL; hr = m_pDxDiagProvider->Initialize( &dxDiagInitParam ); if( FAILED(hr) ) { return false; } hr = m_pDxDiagProvider->GetRootContainer( &m_pDxDiagRoot ); if( FAILED(hr) ) { return false; } return true; } //////////////////////////////////////////////////////////////////////////////// // DxDiag でSystem情報を取得 //////////////////////////////////////////////////////////////////////////////// bool CDxDiagLib::GetSyatemInfo( void ) { HRESULT hr; IDxDiagContainer* pObject = NULL; DWORD nInstanceCount = 0; DWORD nItem = 0; DWORD nCurCount = 0; // "DxDiag_SystemInfo" を取得 if( FAILED( hr = m_pDxDiagRoot->GetChildContainer( L"DxDiag_SystemInfo", &pObject ) ) ) { return false; } // 情報保存領域の確保 ZeroMemory(&g_DxDiagSysInfo, sizeof(g_DxDiagSysInfo)); if( FAILED( hr = GetStringValue( pObject, L"szOSExLongEnglish", g_DxDiagSysInfo.cOS , sizeof(g_DxDiagSysInfo.cOS) ) ) ) { SAFE_RELEASE( pObject ); return false; } if( FAILED( hr = GetStringValue( pObject, L"szSystemManufacturerEnglish", g_DxDiagSysInfo.cManufacturer , sizeof(g_DxDiagSysInfo.cManufacturer) ) ) ) { SAFE_RELEASE( pObject ); return false; } if( FAILED( hr = GetStringValue( pObject, L"szSystemModelEnglish", g_DxDiagSysInfo.cModel , sizeof(g_DxDiagSysInfo.cModel) ) ) ) { SAFE_RELEASE( pObject ); return false; } if( FAILED( hr = GetStringValue( pObject, L"szProcessorEnglish", g_DxDiagSysInfo.cProcessor , sizeof(g_DxDiagSysInfo.cProcessor) ) ) ) { SAFE_RELEASE( pObject ); return false; } if( FAILED( hr = GetStringValue( pObject, L"szPhysicalMemoryEnglish", g_DxDiagSysInfo.cMemory , sizeof(g_DxDiagSysInfo.cMemory) ) ) ) { SAFE_RELEASE( pObject ); return false; } SAFE_RELEASE( pObject ); return true; } よろしくお願いいたします。

  • Directxについて

    1つご教授お願い申したいのですが、 HRESULT DrowInitialize(HWND hWnd) { LPDIRECT3D9 g_pD3D; D3DPRESENT_PARAMETERS g_D3DPP; g_pD3D = Direct3DCreate9(D3D_SDK_VERSION); if(g_pD3D==NULL) { return S_FALSE; } ZeroMemory(&g_D3DPP,sizeof(g_D3DPP)); g_D3DPP.Windowed =TRUE; g_D3DPP.SwapEffect =D3DSWAPEFFECT_DISCARD; g_D3DPP.BackBufferFormat = D3DFMT_UNKNOWN; HRESULT hr = g_pD3D->CreateDevice(D3DADAPTER_DEFAULT,D3DDEVTYPE_HAL,hWnd, D3DCREATE_HARDWARE_VERTEXPROCESSING,&g_D3DPP,&pd3dDevice); if(FAILED(hr)) { hr = g_pD3D->CreateDevice(D3DADAPTER_DEFAULT,D3DDEVTYPE_HAL,hWnd, D3DCREATE_SOFTWARE_VERTEXPROCESSING,&g_D3DPP,&pd3dDevice); if(FAILED(hr)) { hr =g_pD3D->CreateDevice(D3DADAPTER_DEFAULT,D3DDEVTYPE_REF,hWnd, D3DCREATE_SOFTWARE_VERTEXPROCESSING,&g_D3DPP,&pd3dDevice); if(FAILED(hr)) { return S_FALSE; } } } return S_OK; } なのですが、これが通らなくて困っています。(S_FALSEを通ってしまいます)S_OKを通るにはどうしたらいいのでしょうか。わかる方いらしたらよろしくお願いします。

  • 描画について

    サイズを綺麗に描画したいのですが(サイズの範囲(rightとbottom)が微妙にずれている)どうしたら描画できるでしょうか? ここら辺かな?と思うところを載せます。 HRESULT ReadBMP(ID3DXSprite** g_pSprite,LPCTSTR lpszFilename,DDXTEX* g_pTexture) { HRESULT hr = S_FALSE; UINT uLevel = 0; IDirect3DSurface9* pSurface = NULL; lstrcpy(g_pTexture->m_Filename,lpszFilename); g_pTexture->m_clrAlpha=g_colorKey; g_pTexture->m_pTexture=NULL; // スプライト情報の生成 if (SUCCEEDED(hr)) hr = ::D3DXCreateSprite(g_pd3dDevice, g_pSprite); if (SUCCEEDED(hr)) hr = ::D3DXCreateTextureFromFileEx(g_pd3dDevice, g_pTexture->m_Filename, 680, 460, 1, D3DUSAGE_RENDERTARGET, D3DFMT_UNKNOWN, D3DPOOL_DEFAULT, D3DX_DEFAULT, D3DX_DEFAULT, g_pTexture->m_clrAlpha, NULL, NULL, &g_pTexture->m_pTexture); if (SUCCEEDED(hr)) hr = g_pTexture->m_pTexture->GetSurfaceLevel(uLevel, &pSurface); // サーフェイス取得 if (SUCCEEDED(hr)) hr = pSurface->GetDesc(&g_sSurfaceInfo); if (pSurface != NULL) pSurface->Release(); pSurface = NULL; // 失敗したら破棄 if (FAILED(hr)) DestroySplite(*g_pSprite,g_pTexture); return hr; } よろしくお願いします。

  • 十字ボタンのデータについて

    連続して質問して申し訳ありませんがどうか質問させてください。 早速ですがDirectInputのモジュールを作っているんですが、 ジョイスティックからのデータの受け取りで、 各ボタンは問題ないのですが、十字ボタンからのデータを、 うまく認識してくれません。 ●Input.h --省略-- class Input{ public: BOOL JoyData(int ButtonNo); BOOL UP() {return JoyData(0);} BOOL DOWN() {return JoyData(1);} }; ●Input.cpp BOOL Input::JoyData(int No) { DIJOYSTATE2 js; m_pJoystick->Acquire(); m_pJoystick->GetDeviceState(sizeof(DIJOYSTATE2), &js); switch(ButtonNo){ case 0: if(js.lY < 0) return TRUE; // Up break; case 1: if(js.lY > 0) return TRUE; // DOWN break; } } ●Main.cpp HRESULT hr; if( FAILED( hr = CMyD3DApplication::FrameMove(fElapsedTime))) return hr; D3DXMATRIX matWorld; D3DXMATRIX matRotY; D3DXMATRIX matRotX; m_DInput.JoyUpdate(); if(m_DInput.UP()) m_fWorldRotX += m_fElapsedTime * 0.5f; //UP if(m_DInput.DOWN()) m_fWorldRotX -= m_fElapsedTime * 0.5f; //DOWN D3DXMatrixRotationX( &matRotX, m_fWorldRotX ); ポリゴン一つ表示させているのですが、十字ボタンを押していないのに勝手に 下側に動き出してしまうのです。 十字ボタンはどの様な値でゲームパッドからデータを受け取っているのでしょうか この十字ボタンがうまく動かない現象どうかご教授おねがいします。

  • BHO-3

    いつもお世話になっています。 STDMETHODIMP CHelloWorldBHO::SetSite(IUnknown* pUnkSite) { HRESULT hr = S_OK; if (m_pSite != NULL){ m_pSite->Release(); m_pSite = NULL; } if (pUnkSite != NULL) { IHTMLDocument3 *pDocument3; HRESULT hr2 = pUnkSite->QueryInterface(IID_IHTMLDocument3, (void **)&pDocument3); if (SUCCEEDED(hr2)){ PutEventHandler(pDocument3); } ////////////////////////////// // IWebBrowser2 へのポインタをキャッシュします。 HRESULT hr = pUnkSite->QueryInterface(IID_IWebBrowser2, (void **)&m_spWebBrowser); if (SUCCEEDED(hr)) { // DWebBrowserEvents2 からのイベントをシンクに登録します。 hr = DispEventAdvise(m_spWebBrowser); if (SUCCEEDED(hr)) { m_fAdvised = TRUE; } } 上のコードの IHTMLDocument3 *pDocument3; HRESULT hr2 = pUnkSite->QueryInterface(IID_IHTMLDocument3, (void **)&pDocument3); if (SUCCEEDED(hr2)){ PutEventHandler(pDocument3); } ですが、 HRESULT hr2 = pUnkSite->QueryInterface(IID_IHTMLDocument3, (void **)&pDocument3); の部分で失敗します。 HRESULT hr = pUnkSite->QueryInterface(IID_IWebBrowser2, (void **)&m_spWebBrowser); if (SUCCEEDED(hr)) { // DWebBrowserEvents2 からのイベントをシンクに登録します。 hr = DispEventAdvise(m_spWebBrowser); if (SUCCEEDED(hr)) { m_fAdvised = TRUE; } } が、上手く動くのでまねをしたのですが上手く行きません。 すみませんが、アドバイスお願いします。

  • 前回質問させて頂き、改善できるところはしました。

    前回質問させて頂き、改善できるところはしました。 再度駄目な所をご指摘お願いします。 仕様は出来るだけ標準関数に近いものを自作したいと思っています。 //---------------------------- MyStrstr ----------------------------------// char *MyStrstr(const char *str1, const char *str2) { const char *p1 = str1; const char *p3 = str1; const char *p2 = str2; while(*p1 != *p2 && *p1 && *p2) { *p1++; *p3++; } while(*p1 == *p2){ *p1++; *p2++; } return (*p2 ? NULL : (char*)p3); } //------------------------------ 終了 ------------------------------------// //---------------------------- MyStrcat ----------------------------------// char *MyStrcat(char *str1, const char *str2) { char *p1 = str1; const char *p2 = str2; while(*p1 != NULL){ p1++; } if(*p2){ while(*p2 != NULL){ *p1 = *p2; p1++; p2++; } } if(*p2 == NULL){ *p1 = *p2; } return p1; } //------------------------------ 終了 ------------------------------------// //---------------------------- MyStrcmp ----------------------------------// int MyStrcmp(const char *str1, const char *str2) { const char *p1 = str1; const char *p2 = str2; while(*p1 != NULL || *p2 != NULL){ if(*p1 == *p2){ p1++; p2++; }else{ if(*p1 < *p2) return -1; if(*p1 > *p2) return 1; } } return 0; } //------------------------------ 終了 ------------------------------------// //----------------------------- MyMemcpy -----------------------------------// void *MyMemcpy(void *str1, void *str2, size_t n) { char *p1 = (char*)str1; char *p2 = (char*)str2; while(n--){ *p1 = *p2; p1++; p2++; } return str1; } //------------------------------ 終了 ------------------------------------// //---------------------------- MyStrcpy ----------------------------------// char *MyStrcpy(char *str1, const char *str2) { char *p1 = str1; const char *p2 = str2; while( *p2 != NULL){ *p1 = *p2; p1++; p2++; } if(*p2 == NULL){ *p1 = *p2; } return p1; } //------------------------------ 終了 ------------------------------------// //---------------------------- MyMe

  • BHO-2

    http://eternalwindows.jp/browser/mshtml/mshtml01.html の関数を、 http://msdn.microsoft.com/ja-jp/library/bb250489(v=vs.85).aspx のなかに組み込みたいと思っています。 BOOL CHelloWorldBHO::GetDocumentFromIE(IHTMLDocument3 **pp) { HWND hwnd; UINT uMsg; LRESULT lResult; HRESULT hr; EnumChildWindows(FindWindow(TEXT("IEFrame"), NULL), EnumChildProc, (LPARAM)&hwnd); if (hwnd == NULL){ return FALSE; } uMsg = RegisterWindowMessage(TEXT("WM_HTML_GETOBJECT")); if (!SendMessageTimeout(hwnd, uMsg, 0, 0, SMTO_ABORTIFHUNG, 1000, (LPDWORD)&lResult)){ MessageBox(NULL, L"WM_HTML_GETOBJECT", L"BHO", MB_OK); return FALSE; } hr = ObjectFromLresult(lResult, IID_IHTMLDocument3, 0, (void **)pp); if (FAILED(hr)) return FALSE; MessageBox(NULL, L"Hello World! ie-end", L"BHO", MB_OK); return TRUE; } で、 uMsg = RegisterWindowMessage(TEXT("WM_HTML_GETOBJECT")); if (!SendMessageTimeout(hwnd, uMsg, 0, 0, SMTO_ABORTIFHUNG, 1000, (LPDWORD)&lResult)){ MessageBox(NULL, L"WM_HTML_GETOBJECT", L"BHO", MB_OK); return FALSE; } の部分で失敗します。 原因はなんでしょうか・ VS2005 と Win7 を使っています。 MessageBox(NULL, L"WM_HTML_GETOBJECT", L"BHO", MB_OK); はバグの確認のため入れてあります。 アドバイスよろしくお願いします。

専門家に質問してみよう