DirectInputたぶん完全解説・準備編

さーて記念すべき第3回は?(どこを記念するんだよゲシッ
DirectX9 DirectInputたぶん完全解説です。。。
「一回で解説しちゃったら連載にならないじゃないか!」
と、思っておられる方もご心配なくDirectGraphic全く自信ありませんから^^;
尚、コードはすべて私のサンプルコードからの引用となっております。

C#におけるDirectXプログラミングを行うにあたって・・・

C#でDirectX9を利用する場合Managed DirectXを利用します。
DirectX SDKはこちらと(http://www.microsoft.com/japan/msdn/directx/downloads.asp)・・・リンクを張ると・・・SDK昨日付で更新されてるorzしかも、フルパッケージだよorz・・・ぁー23時頃動作確認とって再度書き込みます。なんか、ダウンロード時にWindoesのライセンス認証がありますので23時前にみてすぐ動かしてみたい方今の内にダウンロードを・・・インストールはしないでください、おすすめのインストール方法がありますので^^;

SDKのダウンロードとインストール(最後まで読んでから作業を!

 動作確認とれました!(いやぁ〓マイナーアップデートでよかった・・・)そういうわけで、Microsoft DirectX 9.0 SDK Update (February 2005)となります。Updateとついておりますが、フルパッケージですのでこの単体でSDKは完了です。インストール時はDirectX Documentationをインストールしないことをおすすめします。そして、SDKをダウンロードするのと同じページでMicrosoft DirectX 9.0 Update (October 2004) 日本語ドキュメントをインストールしてください。最新ではありませんが重複しませんので作業が楽になります。

設定

 DirectXをVC#で使用するにあたって、まず必要なのは参照設定の追加です。メニューバーのプロジェクト→参照の追加 又は ソリューションエクスプローラで参照設定を右クリック→参照の追加でタブ.NETのコンポネートMicrosoft.DirectXと今回はDirectInputを使用しますので、Microsoft.DirectX.DirectInputを選択して追加してください。動作確認をとったコンポネートのバージョンは両方とも1.0.2902.0となります。その後、コンポネートをコードに登録してください、コードの一番上の段です。(↓このように太文字が追加したもの普通文字は関係ありません。

using System.ComponentModel;
using System.Windows.Forms;
using System.Data;


オブジェクト

 今回、DirectInputの中で私が取り上げるのはキーボードです。ゲームパッドデバッグ用のデバイスを購入せねば無いので少々お待ちを・・・というわけで、デバイスをオブジェクトとして登録します。 public class Form1 : System.Windows.Forms.Formにこのように↓
 public class Form1 : System.Windows.Forms.Form
 {
  private System.Windows.Forms.Button button1;
  private System.Windows.Forms.Button button2;
  private System.ComponentModel.IContainer components;
  private System.Windows.Forms.Label label1;
  ***private System.Windows.Forms.Timer timer1;
  ***Device applicationDevice = null; 
↑の通りついでに初期化。ちなみに書きましたとおりタイマーが存在します。値の取得はDirectInputですが、反映を司るのはタイマーです。よって更新スピードはタイマーに依存するのですが、Intervalをサンプルでは0.1秒(100ミリ秒)としましたが、少々遅い気がしますのでちょうどいい値をお探しください。(当然ですが早くしすぎるとそれだけ重くなります。)
お疲れ様でした、設定は完了です。次はコード内部に入ります。

DirectInputたぶん完全解説・メソッド・・・開始

コードの内部へ・・・

 コードの内部に入るにあたり、書かなければならないコードに関して説明いたします。必要なメソッドは以下の通りです。
・アプリケーション起動時のデバイス及び周辺環境の設定とデバイスのアクセス権取得
・アクセス権取得、環境設定失敗時及び終了時のリセットとリソースの解除
・アプリケーション切り替え時のアクセス権再取得
・コード中枢(値の取得)
・タイマー(データ更新)
 どれも易しくは無いですが、理解すると簡単です。もっとも理解が難しいのがコード中枢で、おわかりでしょうが最も簡単ながら何よりも重要なのが「アクセス権取得、環境設定失敗時及び終了時のリセットとリソースの解除」です。今回、リセット関係のメソッドがFreeDirectInput何が押されたかのboolをWhatkeypushとしてあります。メソッドの説明順序は書きました通りに行っていきます。

アプリケーション起動時のデバイス及び周辺環境の設定とデバイスのアクセス権取得

 ここが、入り口です。ここで、エラーの洗い出しをしてしまいます。実際、使用する場合アプリケーション起動時に行う動作となります。ちなみに、ここで洗い出してしまうので後は省略w

   if(null !=applicationDevice)         //If デバイスが初期値ではない
   {
    FreeDirectInput();           //デバイス解除占用終了メソッド呼び出し
    return;              //If end中止戻る
   }

↑まぁ、スッカラカンにしたばかりなので、ここで躓くことはないとおもいますが、デバイスがスッカラカンかどうか確認して、もしもスッカラカンになっていなかったらここで、解除用メソッドを呼び出し、初期値に戻します。

   timer1.Enabled = false;           //タイマー無効
   FreeDirectInput();
   CooperativeLevelFlags coopFlags;        //占用関連設定

 タイマーを無効にしてDirectInputが本格的に動き出すのを防止します。そして、一応再度デバイスを洗い初期値に戻します。その後占用関連設定の変数をセットします。

   try
   {
    applicationDevice = new Device(SystemGuid.Keyboard);  //デバイスをキーボードに設定
   }
   catch(InputException)           //If例外発生
   {
    FreeDirectInput();
    MessageBox.Show("キーボード占用失敗");      //メッセージボックス
    return;              //If end戻る
   }

 デバイスをキーボードに設定します。もしも、設定できなかった場合メッセージボックスを出すようになっています。InputExceptionとはDirectInputの基底例外タイプです。

   try
   {
//占用関連設定 バックグラウンドによる完全占用はセキリュティ上不可
    coopFlags = CooperativeLevelFlags.NonExclusive;    //このアプリ動作時他アプリデバイス使用可
    coopFlags |= CooperativeLevelFlags.Foreground;    //このアプリが最前面時のみ有効
    applicationDevice.SetCooperativeLevel(this, coopFlags);
   }
   catch(InputException dx)          //If例外発生
   {
//↓不可警告、占用関連設定に問題あり
    if (dx is UnsupportedException)
    {
     FreeDirectInput();
     MessageBox.Show("キーボードを占用できませんでした");
     return;             //If end戻る
    }
   }

 前に出しました、占用関連設定を行うべくcoopFlagsに値を放り込みます。項目は2種類5項目以下の通りです。

CooperativeLevelFlags.Background

バックグラウンド動作アプリケーションが非アクティブでも値の所得が可能

CooperativeLevelFlags.Foreground

最前面(アクティブ時)限定で値の取得が可能

CooperativeLevelFlags.Exclusive

他のアプリケーションにデバイスへのアクセス権が無くなります。

CooperativeLevelFlags.NonExclusive

他のアプリケーションもデバイスへアクセス可能です。

CooperativeLevelFlags.NoWindowsKey

キー無効化

   applicationDevice.Acquire();         //例外排除及び設定完了アクセス権取得・・・占用
   timer1.Enabled = true;           //タイマー有効

 例外やエラー発生の可能性を排除したので、アクセス権を取得、タイマーを有効にします。


 お疲れ様でした、おそらく一番長い開始のメソッドが完了です。

DirectInputたぶん完全解説・メソッド・・・中盤

アクセス権取得、環境設定失敗時及び終了時のリセットとリソースの解除

まぁ、前回も書きましたが、このメソッドはFreeDirectInputとしてサンプルコードも説明しましたので、そのままペタ

  private void FreeDirectInput()          //デバイス解除占用終了メソッド呼び出し
  {
   if (null != applicationDevice)         //デバイスが初期値ではない
   {
    applicationDevice.Unacquire();        //アクセス権破棄占用解除
    applicationDevice.Dispose();        //デバイスリソース解除
    applicationDevice = null;         //デバイス初期化
   }
  }

説明する必要ナッシング!グレイト(マテ・・・だいぶん睡魔が回ってきた・・・
ちなみに終了時には必ず、初期化したいところにもこれ↓

FreeDirectInput();

を入れるだけでOK!

アプリケーション切り替え時のアクセス権再取得

   if (null != applicationDevice)         //デバイス初期ではない
   {
    try{applicationDevice.Acquire();}       //占用再開(再開なのでチェック省略)
    catch (DirectXException){}         //すべての例外(形式だけなので無用、無視)
   }

ぁ〓これも説明する必要ないなぁ〓サンプルコードがんばったみたいだし公開しちゃうかー・・・

タイマー(データ更新)

行数の関係で先にタイマーを・・・ペタ

   if (!Whatkeypush())            //データ異常
   {
    label1.Enabled = false;          //label1ロック
    MessageBox.Show("データー読み込み失敗終了");
    this.Close();            //アプリ終了
   }

ぇ・・・あ、ちなみにサンプルはキーボードから得た値をlabel1にだします。
というわけで、このコードの意味(予想)ぉぃ
Whatkeypushが異常ならアプリ終了・・・あれ・・・文章構成能力低下中・・・


さて、最後は中枢果たして書けるのか^^;

DirectInputたぶん完全解説・メソッド・・・中枢

コード中枢(値の取得)

やってきました!ちゅーす〓(頭逝ってます
うっ、またしても解説の必要が・・・・ない
平常時の頭が睡魔に捲かれた頭とPen4とcleくらいの差があることを実感中
というわけで、まんまペタ

  bool Whatkeypush()             //何が押されたか
  {
   string textnow = String.Empty;         //String変数初期化
   KeyboardState state = null;          //キーボード状態初期化

   if (null == applicationDevice)         //デバイス初期状態
    return true;            //返り値true戻す

   InputException ie = null;          //DirectInput例外 ie値無し
   try
   {
    state = applicationDevice.GetCurrentKeyboardState();  //stateにデバイスから直接データを取得
   }
   catch (DirectXException)          //↑が失敗した場合
   {
            
    bool loop = true;           //trueの場合ループ
    do               //falseになるまで繰り返す
    {
     try
     {
      applicationDevice.Acquire();      //デバイス占用
     }
     catch(InputLostException)        //アクセス権を失った場合
     {
      loop = true;          //ループ再実行
     }
     catch(InputException inputException)     //新規デバイス初期化占用
     {
      ie = inputException;        //ieにinputExceptionを入れる
      loop = false;          //ループ終了可能
     }
    }while (loop);            //ループfalseのため終了
//↓例外発生 他のアプリケーションが完全占用状態又は占用不能
    if (ie is OtherApplicationHasPriorityException || ie is NotAcquiredException)
     label1.Text = "キーボードを占用できません。他のアプリケーションを終了してください";

    return true;            //返り値true戻す 
   }
    
   for (Key k = Key.Escape; k <= Key.MediaSelect; k++)    //falseになるまで繰り返す(MediaSelectの方が優先度高)
   {
    if (state[k])            //デバイスより直接得たデータをkとする
     textnow += k.ToString() + " ";       //kの後にスペースを入れたものをtextnowに追加
//ToStringはバイナリを文字にしている・・・だったはず。
   }
    
   if (label1.Text != textnow)          //もしtextnowとlabel1.textが等しくない場合
    label1.Text = textnow;          //label1.textにtextnowを入れる
    
   return true;             //戻す
  }

一応説明足りない部分書き足して、これで完了かな?前も述べたとおりlabel1に結果をだすプログラム

最後に

作成したサンプルプログラム結局アップロードしました。ほしい方はどうぞ
http://jp.thespoke.net/MySpace/GetFile.aspx?ID=640
このプログラム、結局のところ私がC#で作成した初めてのプログラムです。
制作時間6時間、DirectInputの扱いに関してはSDKのサンプルを参考にしました。
いろいろと、お見苦しい点もあると思いますのでお気づきの点があればご指摘して頂けますとうれしいです。ちなみに、”はじめて”のC#なので、ごくごく基本的なところも解説が入っております。


 さて、多重投稿をしてまで解説した理由ですが、一つに私が非常に忘れっぽい人間であること(自分のための解説ページ)もう一つに、C#DirectInputに関して説明したページを見たことがないので、参考になればと思った点(初心者が書いたプログラムなんて動くだけで参考になどならないのにねぇ)この二点です。コードが思ったより短くなったので書いてきたのですが、思ったより遙かに長くなってしまいました。次からは多重投稿にならないようにしつつマウス、ゲームパッドジョイスティックの順にお話しできたらと思います。最終的にはDirectGrphicsに統合されたDirectDorwに近いエリアまでいけたらと思っております。今回の多重投稿に関しては申し訳ございませんでした。


 と、まぁ感想ですがC#思ったより簡単で驚いております。括弧でくくられたVBと思ってもさほど違いが無いのじゃないのかと^^;時間はかかってしまいましたが満足です。