DirectInput ライブラリ構築

随分今更なんだけど、DirectInputのライブラリ構築を朝からちまちまと。
今回使ったのはDirectInput8。
やっと書き上がって、さあテストだーってところで、エラーエラーエラー・・・


何かと思えば、GetDeviceStateがDIERR_INVALIDPARAMを返してる。
自分には大変よくある事で、この手のエラーはぐぐって原因が分かる事が少ない。
(出てくる件数も件数だし・・。)
結果として、あーでもないこーでもないとコードをいじくりまわした挙げ句、
とても初歩的なミスでした。というオチが解決する前からみえみえである。




落ち着いてプログラムの流れを整理してみる。


1.IDirectInput8インターフェイスの取得
   これはちゃんとできてる。


2.デバイス一覧の取得
   今回はジョイスティック用ライブラリであるので、
     DIDEVTYPE_JOYSTICK
   を引数にEnumDevicesを呼ぶ。
   これもちゃんと成功してる。


3.IDirectInputDevice8インターフェイスの取得
   これも成功。


4.デバイスフォーマット・協調レベルの設定
   今回はジョイスティックなので、デバイスフォーマットは
     c_dfDIJoystick
   にしてある。
   協調レベルは、
     DISCL_FOREGROUND | DISCL_NONEXCLUSIVE
   で、どちらも成功している。


ジョイパッドの値域設定
   FAILEDマクロを使って判定させたところ、ここでまず失敗している。
   X,Y,Z軸を -255 〜 255 に設定してるだけなのに・・・。
   エラー値を調べてみると、DIERR_OBJECTNOTFOUNDが返ってきている。
   要求されたオブジェクトは存在しない。


   DIERR_OBJECTNOTFOUNDの検索結果 49
   DIERR_OBJECTNOTFOUND に一致する日本語のページ 9


   だめだだめだ。すぐグーグル先生に頼ろうとしてしまう。
   オブジェクトといえば、DIPROPRANGEのdwObjか?


      diPropRange.diph.dwObj = DIJOFS_X;


   なるほど、これが存在しないわけね。じゃあ・・・
   EnumObjects を使ってオブジェクトを列挙し、
   ボタン1つ1つにSetPropertyしよう。
   そうすると、結果がそれっぽくなった。


      13個のDIERR_UNSUPPORTEDが出現
          ↓
      4個のSUCCESSが出現
          ↓
      15個のDIERR_UNSUPPORTEDが出現
          ↓
      4個のSUCCESSが出現
          ↓
      2個のDIERR_UNSUPPORTEDが出現


   この4個×2は、PS2のコントローラを繋いでいたので
   左右のスティックの±X,Y軸のことだと思われる。


   これで値域設定は完了!


5.デバイスへのアクセス権取得
   Acquireするだけなんだけど・・・ここでもエラーが!


      DIERR_OTHERAPPHASPRIO
      DIERR_INVALIDPARAM


   この2つが順番に表示された。あれ?デバイスは1個だけのはずなんだけど・・。
   前者をMSDNで調べてみると、



このエラーが返されるのは、デバイスに対するアプリケーションのアクセス権がフォアグラウンド アクセス権であるにもかかわらず、バックグラウンドであるときにデバイスを取得しようとした場合である。


   と書かれている事から・・・試しにDISCL_BACKGROUNDを設定してみると、DI_OKになった。
   だけど、相変わらず2個目の DIERR_INVALIDPARAM が出てくる。
   そして、PS2コンのボタンを押したりしても反応なし。
   デバイスの再取得を行ってみると、DIERR_INVALIDPARAM が1回だけ表示されるところから、
   問題は後者にありそうな感じがする。


   で、後者のエラーについてMSDNで調べてみると、



データ形式が設定されていない場合、IDirectInputDevice8::Acquire は DIERR_INVALIDPARAM を返す。


   と書かれている。おやおや、成功してるはずなんだけども。
   調べてみると、やっぱりDI_OKが返ってきている。
   実際のポーリング前のAcquireも DIERR_INVALIDPARAM が返る。
   一体どの辺がINVALIDなのか、是非お聞かせ願いたいものだ。


   こうなると手詰まりっぽいけど、やっぱり起動時に2回表示される
     

      DIERR_OTHERAPPHASPRIO
      DIERR_INVALIDPARAM


   これが気になる。
   1個しかないデバイス。2回表示されるメッセージ。
   ・・・これは!


   結論を言うと、テスト用プログラムに問題があった\(^o^)/
   ダイアログリソースを使ってたんだけども、


   1.WM_INITDIALOGで明示的にクラスのInitを呼び出し
   2.更に、デバイスリスト更新を呼び出し
   3.デバイスリスト更新処理は、
      ・デストラクタ呼び出し
      ・再びInit
     という流れ。


   で、デストラクタを呼び出してるのがまずいのだろうか、ということで
   Releaseメンバ関数を別に作って、それを呼び出してやったら
   今までのエラーやらなんやらが嘘のように消えた。



  ___
/||     .(|| ∧_∧
.... ___ (     )  どうしてこうなった・・・
 ̄ ̄\三 ⊂/ ̄ ̄ ̄/
       ( ./     /
  ___ /||  (^ν|| ∧_∧
.... ___ ( ^ω^ )  どうしてこうなった!?
 ̄ ̄\三 ⊂/ ̄ ̄ ̄/
       ( ./     /
自分のせいだろ氏ね屑   ___♪  ∧__,∧.∩ /||(^ν^)|| r( ^ω^ )ノ  どうしてこうなった!
.... ___ └‐、   レ´`ヽ   どうしてこうなった!
 ̄ ̄\三   / ̄ ̄ ̄/ノ´` ♪
        ( ./     /
  ___            ∩∧__,∧ /||      ||         _ ヽ(ω^  )7
.... ___         /`ヽJ   ,‐┘
 ̄ ̄\三   / ̄ ̄ ̄/  ´`ヽ、_  ノ
       ( ./     /      `) )


よくある事。
というわけで・・・・・・・・・




  


無事に動きました。やったねほしみ