バッファを使用したキーボードの情報取得
Sivun luontipäivämäärä :
Tällä hetkellä tarkastelemasi sivu ei tue valittua näyttö kieltä.
前回キーボードの情報を取得しましたが、もし、一回の更新時間が長かった場合、キーが複数回押されたりしても、それを1回と認識したり、または押されていないと認識される可能性もあります。今回は「バッファ」を使用することにより、ハードウェアの情報をバッファに蓄積し、ソフト側の影響による情報のご認識を防ぐようにします。
下の図はわざと更新時間を長く取り、次の更新のときに蓄積されたデータを一度に取り出したデータです。
今回のメインコードファイルを載せます。部分的な説明に関してはコードの下の方で説明しています。
MainSample.cs
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using Microsoft.DirectX;
using Microsoft.DirectX.DirectInput;
namespace MDXSample
{
<summary>
メインサンプルクラス
</summary>
public class MainSample : IDisposable
{
<summary>
メインフォーム
</summary>
private MainForm _form = null;
<summary>
キーボードデバイス
</summary>
private Device _keyboradDevice = null;
<summary>
アプリケーションの初期化
</summary>
<param name="topLevelForm">トップレベルウインドウ</param>
<returns>全ての初期化がOKなら true, ひとつでも失敗したら false を返すようにする</returns>
<remarks>
false を返した場合は、自動的にアプリケーションが終了するようになっている
</remarks>
public bool InitializeApplication(MainForm topLevelForm)
{
// フォームの参照を保持
this._form = topLevelForm;
// キーボードデバイスの初期化
try
{
// キーボードデバイスの作成
this._keyboradDevice = new Device(SystemGuid.Keyboard);
// 協調レベルの設定
this._keyboradDevice.SetCooperativeLevel(topLevelForm,
CooperativeLevelFlags.NonExclusive | CooperativeLevelFlags.Background);
}
catch (DirectXException ex)
{
MessageBox.Show(ex.ToString(), "エラー", MessageBoxButtons.OK, MessageBoxIcon.Error);
return false;
}
// バッファサイズを指定
this._keyboradDevice.Properties.BufferSize = 16;
try
{
// キャプチャするデバイスを取得
this._keyboradDevice.Acquire();
}
catch (DirectXException)
{
}
return true;
}
<summary>
メインループ処理
</summary>
public void MainLoop()
{
// バッファが本当に作用しているかテスト
//System.Threading.Thread.Sleep(100);
BufferedDataCollection buffer = null;
try
{
// キーボードの状態をキャプチャ
buffer = this._keyboradDevice.GetBufferedData();
}
catch (DirectXException)
{
try
{
// キャプチャするデバイスを取得
this._keyboradDevice.Acquire();
// キーボードの状態をキャプチャ
buffer = this._keyboradDevice.GetBufferedData();
}
catch (DirectXException)
{
return;
}
}
if (buffer == null)
{
// デバイスをキャプチャできない、またはデータがないとき
return;
}
StringBuilder builder = new StringBuilder();
// バッファに蓄積された情報を読み取る
foreach (BufferedData i in buffer)
{
if (i.Data != 0)
{
builder.Append((Key)i.Offset + " Down" + Environment.NewLine);
}
else
{
builder.Append((Key)i.Offset + " Up" + Environment.NewLine);
}
}
// ラベルに表示
this._form.InputLabel.Text = builder.ToString();
}
<summary>
リソースの破棄をするために呼ばれる
</summary>
public void Dispose()
{
// キーボードデバイスの解放
if (this._keyboradDevice != null)
{
this._keyboradDevice.Dispose();
}
}
}
}
// バッファサイズを指定
this._keyboradDevice.Properties.BufferSize = 16;
バッファサイズを指定します。バッファサイズはデータをどのくらい格納させるかを決めるためのものです。今回は16個分の記憶領域を使用することにします。
BufferedDataCollection buffer = null;
try
{
// キーボードの状態をキャプチャ
buffer = this._keyboradDevice.GetBufferedData();
}
catch (DirectXException)
{
try
{
// キャプチャするデバイスを取得
this._keyboradDevice.Acquire();
// キーボードの状態をキャプチャ
buffer = this._keyboradDevice.GetBufferedData();
}
catch (DirectXException)
{
return;
}
}
バッファに格納されたデータを受け取るには「Device.GetBufferedData」メソッドを使用します。BufferedDataCollection には個々のバッファデータが格納されています。
if (buffer == null)
{
// デバイスをキャプチャできない、またはデータがないとき
return;
}
もし取得に失敗したのなら return します。
StringBuilder builder = new StringBuilder();
// バッファに蓄積された情報を読み取る
foreach (BufferedData i in buffer)
{
if (i.Data != 0)
{
builder.Append((Key)i.Offset + " Down" + Environment.NewLine);
}
else
{
builder.Append((Key)i.Offset + " Up" + Environment.NewLine);
}
}
// ラベルに表示
this._form.InputLabel.Text = builder.ToString();
BufferedDataCollection から個々のバッファデータを調べます。「BufferedData.Data」には、キーを押した時なら「0x80」、放したときなら「0x00」が格納されているので、それで条件分岐可能です。
また、どのキーの情報が格納されているかは BufferedData.Offset で分類できるので「Key」でキャストして調べられます。