web-dev-qa-db-ja.com

C#でキーが押されたかどうかを検出します(A、Bではなく任意)

[編集3]「奇妙な」バージョンを使って「解決」した。少なくとも最も重要なキーについては。 ALTとALT + Aが同じでないことを確認したい(それによってAが押されていないことを確認したい)私の場合はこれで十分です。完璧ではありませんが、そのような小さな問題にはすでに多くの時間がかかります。とにかくすべての答えをありがとう... [編集3]

[EDIT 4] 280Z28 [/ EDIT 4]のおかげでずっときれいに解決しました

修飾キーをチェックする方法と単一のキーをテストする方法を知っています。問題は、キーが押されているかどうかを確認したいということです。次のアプローチは「奇妙」に思えます:-)

C#で記述されたWPFアプリケーション

if (Keyboard.IsKeyDown(Key.A)) return true;
if (Keyboard.IsKeyDown(Key.B)) return true;
if (Keyboard.IsKeyDown(Key.C)) return true;

列挙型だとわかっているので、ループについて考えましたが、使用する「最大数」は何ですか。そして、これは可能ですか?ところで、それは非常に特殊なケースで、通常はイベントを使用しますが、この場合はこの方法で行う必要があります。残念ながら、「リスト」Keyboard.CurrentlyDownKeysはありません。少なくとも私はそれを見ませんでした。

ありがとう、クリス

EDIT:わかりました。大したことのようですが、その理由は次のとおりです。カスタム関数のDictionaryKeyとして機能する「KeySet」を定義しました。誰かが要素をクリックすると、ラッパーはディクショナリを反復処理し、事前定義された「キーセット」のいずれかがアクティブであるかどうかを確認します。

これにより、たとえば次のような単純なトリガーを定義できます。 ALT + A + Bが押された場合、この機能を実行します。別のオプションは、例えばです。 ALT + STRG + Aが押された場合(WPF要素をマウスでクリックしている間)にこの関数を実行します。

現在の実装での唯一の「問題」は、ALTが押された場合に実行するなど、REALキーを含まないキーセットを定義した場合、ALT + Aが押された場合にもトリガーされます。ああ、これを書いていると、別の問題があることに気づきました。現在、ALT + A + B + Cが押された場合にも、ALT + A + Bがトリガーされます。

おそらく私のアプローチは間違っているので、「静的キートラッカー」を作成し、キーセットをその値(イベントを介して取得)と比較する必要があります。これを試してみます。

EDIT 2これは、少なくとも単純な方法では機能していません。 KeyDownにアタッチするFrameworkElementが必要ですが、静的コンストラクターにありません。そして、私は特定の要素のKeyDownEventsには興味がありませんが、「グローバルに」...私はこの問題を延期すると思います。それほど重要ではありません。それでも、誰かが別のアプローチのより良いことを知っているなら...

長い間、気にする人のために、ここにいくつかのコードがあります:

    public class KeyModifierSet
{
    internal readonly HashSet<Key> Keys = new HashSet<Key>();
    internal readonly HashSet<ModifierKeys> MKeys = new HashSet<ModifierKeys>();

    public override int GetHashCode()
    {
        int hash = Keys.Count + MKeys.Count;
        foreach (var t in Keys)
        {
            hash *= 17;
            hash = hash + t.GetHashCode();
        }
        foreach (var t in MKeys)
        {
            hash *= 19;
            hash = hash + t.GetHashCode();
        }
        return hash;
    }

    public override bool Equals(object obj)
    {
        return Equals(obj as KeyModifierSet);
    }
    public bool Equals(KeyModifierSet other)
    {
        // Check for null
        if (ReferenceEquals(other, null))
            return false;

        // Check for same reference
        if (ReferenceEquals(this, other))
            return true;

        // Check for same Id and same Values
        return Keys.SetEquals(other.Keys) && MKeys.SetEquals(other.MKeys);
    }

    public bool IsActive()
    {
        foreach (var k in Keys)
            if (Keyboard.IsKeyUp(k)) return false;

        if ((Keys.Count == 0) && !Keyboard.IsKeyDown(Key.None)) return false;


        foreach (var k in MKeys)
            if ((Keyboard.Modifiers & k) == 0) return false;

        if ((MKeys.Count == 0) && Keyboard.Modifiers > 0) return false;

        return true;
    }


    public KeyModifierSet(ModifierKeys mKey)
    {
        MKeys.Add(mKey);
    }
    public KeyModifierSet()
    {

    }
    public KeyModifierSet(Key key)
    {
        Keys.Add(key);
    }
    public KeyModifierSet(Key key, ModifierKeys mKey)
    {
        Keys.Add(key);
        MKeys.Add(mKey);
    }
    public KeyModifierSet Add(Key key)
    {
        Keys.Add(key);
        return this;
    }
    public KeyModifierSet Add(ModifierKeys key)
    {
        MKeys.Add(key);
        return this;
    }
}
11
[DllImport("user32.dll", EntryPoint = "GetKeyboardState", SetLastError = true)]
private static extern bool NativeGetKeyboardState([Out] byte[] keyStates);

private static bool GetKeyboardState(byte[] keyStates)
{
    if (keyStates == null)
        throw new ArgumentNullException("keyState");
    if (keyStates.Length != 256)
        throw new ArgumentException("The buffer must be 256 bytes long.", "keyState");
    return NativeGetKeyboardState(keyStates);
}

private static byte[] GetKeyboardState()
{
    byte[] keyStates = new byte[256];
    if (!GetKeyboardState(keyStates))
        throw new Win32Exception(Marshal.GetLastWin32Error());
    return keyStates;
}

private static bool AnyKeyPressed()
{
    byte[] keyState = GetKeyboardState();
    // skip the mouse buttons
    return keyState.Skip(8).Any(state => (state & 0x80) != 0);
}
11
Sam Harwell

かなり古い質問ですが、誰かがこれに遭遇し、外部dllを使用したくない場合は、可能なキーを列挙してループすることができます。

    bool IsAnyKeyPressed()
    {
        var allPossibleKeys = Enum.GetValues(typeof(Key));
        bool results = false;
        foreach (var currentKey in allPossibleKeys)
        {
            Key key = (Key)currentKey;
            if (key != Key.None)
                if (Keyboard.IsKeyDown((Key)currentKey)) { results = true; break; }
        }
        return results;
    }

関数の外部で列挙型を実行し、後で使用できるようにリストを保持することで、これを少し最適化できます。

4
Andy

XNAフレームワークを使用すると、以下を使用して、いずれかのキーが押されたかどうかを確認できます。

Keyboard.GetState().GetPressedKeys().Length > 0
3
Carlc75

このコードはどこから実行されていますか?イベントハンドラーにありますか?多くのフォームとコントロールは、KeyPressイベントとKeyDownイベントを発生させます。これらのイベントを調べて、いずれかが発生したときにフラグをtrueに設定することをお勧めします。また、キーがリリースされたときに通知する対応するイベントをリッスンする必要があります(KeyUpもそうだと思います)。

キー列挙には、ゼロ(0)の列挙値があります。これは、基本的に「キーが押されていません」をテストします。これは、「キーが押された場合」の反対です。したがって、このようなものが機能する可能性があります。

If !GetKeyState(0)==True then
    Do Something
End If

または

If GetKeyState(0)==False then
    Do Something
End If
0
ILIAS BURKETT

Windows.Formsを使用している場合は、KeyDownイベントを使用し、適切なKeyEventArgsを使用して特定のキーを読み取ります。 KeyCode変数のKeyEventArgsプロパティにアクセスできます。

範囲を確認するには、AとZの間と言います。

if (e.KeyCode>=Keys.A && e.KeyCode<=Keys.Z)
{
  // do stuff...or not
}
0

http://sourceforge.net/projects/keystate/ は「特別な」キーを示しています。それ以外の場合は、それらを監視する必要があると思います。これをシステム全体で実行したいような音はありますか?何を達成しようとしていますか?

キーダウンイベントごとにカウンターをインクリメントし、キーアップイベントごとにカウンターをデクリメントできます。カウンターがゼロの場合、キーは押されていません。

0
xpda