7

現在キーボードで押されている「すべてのキー」を取得するには、何を使用する必要がありますか?コントロールがいっぱいになると、Form.KeyPress += new EventHandler()ほとんど何もしません。KeyDown、KeyUp、その他何をしていても、それを呼び出すことはありません...そして、ええ、私はそれらの使い方を知っています。

したがって、押されたキーをチェックできる関数がシステムにあれば、使用されたキーの配列などが返されます。正しい方向に向けられれば幸いです。

4

4 に答える 4

15

キーボードのすべてのキーの状態を照会したいようです。そのための最適な関数は Win32 API 呼び出しですGetKeyboardState

その機能に相当する管理された優れた機能があるとは思いません。そのための PInvoke コードはかなり単純です

[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool GetKeyboardState(byte [] lpKeyState);

var array = new byte[256];
GetKeyboardState(array);

これによりbyte[]、システム内のすべての仮想キーのアップ/ダウン状態が読み込まれます。上位ビットが設定されている場合、仮想キーは現在押されています。Key仮想キー コードへの a のマッピングbyteは、数値の部分のみを考慮して行われKeyます。

public static byte GetVirtualKeyCode(Key key) {
  int value = (int)key;
  return (byte)(value & 0xFF);
}

上記はほとんどのKey値で機能しますが、修飾キーには注意する必要があります。値とはKeys.Alt、技術的に修飾子であり、キー値ではないため、ここでは機能しません。修飾子を使用するには、実際に関連付けられたキー値、などを使用する必要があります (実際には Key で終わるものは何でも)Keys.ControlKeys.ShiftKeys.ControlKeyKeys.LShiftKey

したがって、特定のキーが設定されているかどうかを確認するには、次のようにします。

var code = GetVirtualKeyCode(Key.A);
if ((array[code] & 0x80) != 0) {
  // It's pressed
} else { 
  // It's not pressed
}
于 2012-05-07T14:56:05.227 に答える
6

JaredPar の回答を少し拡張しました。次のメソッドは、現在押されているすべてのキーのコレクションを返します。

using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Windows.Input;

private static readonly byte[] DistinctVirtualKeys = Enumerable
    .Range(0, 256)
    .Select(KeyInterop.KeyFromVirtualKey)
    .Where(item => item != Key.None)
    .Distinct()
    .Select(item => (byte)KeyInterop.VirtualKeyFromKey(item))
    .ToArray();

/// <summary>
/// Gets all keys that are currently in the down state.
/// </summary>
/// <returns>
/// A collection of all keys that are currently in the down state.
/// </returns>
public IEnumerable<Key> GetDownKeys()
{
    var keyboardState = new byte[256];
    GetKeyboardState(keyboardState);

    var downKeys = new List<Key>();
    for (var index = 0; index < DistinctVirtualKeys.Length; index++)
    {
        var virtualKey = DistinctVirtualKeys[index];
        if ((keyboardState[virtualKey] & 0x80) != 0)
        {
            downKeys.Add(KeyInterop.KeyFromVirtualKey(virtualKey));
        }
    }

    return downKeys;
}

[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool GetKeyboardState(byte[] keyState);
于 2015-05-27T02:41:22.313 に答える
1

アプリケーション内のどのコントロールにフォーカスがあるかに関係なく、アプリケーションがアクティブなときにすべてのキーストロークを知る必要がある場合はKeyPreview、フォームのプロパティを使用できます。

プロパティをtrueに設定し、フォームで目的のキーイベントをサブスクライブするだけです。これで、具体的なコントロールに転送される前に、アプリケーション内のすべてのキーストロークを受け取ることができます。これにより、アプリケーションに反応し、Cancelプロパティをtrueに設定してコントロールへの転送をキャンセルできます。

アプリケーションがアクティブでないときに押されたキーを受け取る必要がある場合は、ある種の低レベルのキーボードフックが必要です。私はそれをテストしませんでしたが、CodeProjectに関するこの記事はこの場合非常に有望に見えます。

于 2012-05-08T07:31:37.313 に答える
0

そのフォーム内の別の子コントロールに現在フォーカスがある場合でも、フォームにフォーカスがあるときにキーが押されると発生するPreviewKeyDownイベントを探していると思います。

于 2012-05-07T14:52:37.823 に答える