キーボードの情報を取得

頁面創建日期 :

當前顯示的頁面不支援所選的顯示語言。

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();
}

アプリケーションを終了するときにデバイスを解放しています。