キーボードの情報を取得
Η σελίδα που προβάλετε αυτήν τη στιγμή δεν υποστηρίζει την επιλεγμένη γλώσσα εμφάνισης.
DirectInput を使用してキーボードの状態を取得します。各キーを押すとそのキーがフォームに表示されます。
今回のメインコードファイルを載せます。部分的な説明に関してはコードの下の方で説明しています。
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;
}
try
{
// キャプチャするデバイスを取得
this._keyboradDevice.Acquire();
}
catch (DirectXException)
{
}
return true;
}
<summary>
メインループ処理
</summary>
public void MainLoop()
{
Key[] pushKeys = null;
try
{
// 押されたキーをキャプチャ
pushKeys = this._keyboradDevice.GetPressedKeys();
}
catch (DirectXException)
{
try
{
// キャプチャするデバイスを取得
this._keyboradDevice.Acquire();
// 押されたキーを再度キャプチャ
pushKeys = this._keyboradDevice.GetPressedKeys();
}
catch (DirectXException)
{
}
}
if (pushKeys == null)
{
// デバイスをキャプチャできない、またはキーが押されていないとき
return;
}
// 文字列を追加していく
StringBuilder builder = new StringBuilder();
foreach (Key i in pushKeys)
{
builder.Append(i.ToString() + Environment.NewLine);
}
// ラベルに押されているキーを列挙
this._form.InputLabel.Text = builder.ToString();
}
<summary>
リソースの破棄をするために呼ばれる
</summary>
public void Dispose()
{
// キーボードデバイスの解放
if (this._keyboradDevice != null)
{
this._keyboradDevice.Dispose();
}
}
}
}
<summary>
キーボードデバイス
</summary>
private Device _keyboradDevice = null;
キーボードの状態を取得するときなど、大抵の場合この「Device」クラスを使用することになります。このDeviceクラスはキーボードのほかにマウスやジョイスティックにも使用されます。
// キーボードデバイスの初期化
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;
}
まず一番最初にキーボードのデバイスを作成します。Device コンストラクタには「SystemGuid.Keyboard」を指定するようにします。これは GUID というものに関係するのですが、DirectX とは別項目になるので説明は割愛します。とりあえずこれを指定すると思ってかまいません。
次に協調レベルというものを設定します。これは他のアプリケーションとデバイスが競合するとき、アクセス権をどちらが扱うかなどを決定するためのものです。 このフラグはどのように指定するかは開発者が決めます。そのソフトにあわせて決めてください。
Device.SetCooperativeLevel メソッド |
|
---|---|
デバイスの指定したコントロールに対する協調レベルを確立します | |
parent | 対象となるコントロール。通常メインで使用しているフォームを指定 |
flags | 協調レベルフラグ。CooperativeLevelFlags から組み合わせて指定。下を参照 |
CooperativeLevelFlags 列挙型 |
|
---|---|
NoWindowsKey | ウィンドウのキーを無効にします。他のフラグと組み合わせ可。 |
Background | コントロールがアクティブでないときも、デバイスの入力を受け取ることが出来ます。Foreground, Exclusive 以外と組み合わせ可。 |
Foreground | コントロールがアクティブのときのみ、デバイスの入力を受け取れます。Background 以外と組み合わせ可。 |
NonExclusive | デバイスを他のアプリケーションと共有できます。Exclusive 以外と組み合わせ可。 |
Exclusive | 他のアプリケーションはこのデバイスを使用することは出来ません。キーボードやマウスの場合、このフラグと Background の組み合わせは絶対に行ってはいけません。NonExclusive, Background 以外と組み合わせ可。 |
もしデバイスの作成などが失敗した場合は、メッセージボックスを表示して終了するようにしています。
try
{
// キャプチャするデバイスを取得
this._keyboradDevice.Acquire();
}
catch (DirectXException)
{
}
Device.Acquire メソッドにより、実際にデバイスを取得できるようになります。しかし、現時点でフォームはまだ表示されていないので、協調フラグで「CooperativeLevelFlags.Foreground」を指定している場合は、このメソッドは失敗します。そのため try-catch で例外を受け取れるようにしています。ただ、例外が出てもそのままスルーするようにしています。CooperativeLevelFlags.Foreground を指定していればこれは当たり前に発生するので、アプリケーションを終了させるようなことはしなくてもいいのです。
Key[] pushKeys = null;
try
{
// 押されたキーをキャプチャ
pushKeys = this._keyboradDevice.GetPressedKeys();
}
catch (DirectXException)
{
try
{
// キャプチャするデバイスを取得
this._keyboradDevice.Acquire();
// 押されたキーを再度キャプチャ
pushKeys = this._keyboradDevice.GetPressedKeys();
}
catch (DirectXException)
{
}
}
実際のメインループの処理です。
キーボードデバイスの状態が受け取れる状態になっていれば、「Device.GetPressedKeys」メソッドで、押されているキーの配列を受け取ることが出来ます。しかし、デバイスの状態が受け取れる状態で無い場合、例外が発生する可能性があるので、その場合は、「Device.Acquire」メソッドでデバイスの取得を試みます。成功した場合は再度キーの状態を受け取るようにします。それでもデバイスが取得できなかった場合はいったんスルーしています。
if (pushKeys == null)
{
// デバイスをキャプチャできない、またはキーが押されていないとき
return;
}
もしデバイスが取得できなかった場合は keys は null なので、そのときはメソッドを抜けるようにしています。
// 文字列を追加していく
StringBuilder builder = new StringBuilder();
foreach (Key i in pushKeys)
{
builder.Append(i.ToString() + Environment.NewLine);
}
// ラベルに押されているキーを列挙
this._form.InputLabel.Text = builder.ToString();
押されているキーをラベルに表示させる処理を行っています。
StringBuilder クラスを使用すると文字列を高速に連結できるので、何度も連結する可能性がある場合は有効です。連結は「StringBuilder.Append」メソッドで行います。
Environment.NewLine はテキストの改行コードです。
最後にフォームのラベルテキストに作成した文字列をコピーしています。
// キーボードデバイスの解放
if (this._keyboradDevice != null)
{
this._keyboradDevice.Dispose();
}
アプリケーションを終了するときにデバイスを解放しています。