現在キーボードで押されている「すべてのキー」を取得するには、何を使用する必要がありますか?コントロールがいっぱいになると、Form.KeyPress += new EventHandler()
ほとんど何もしません。KeyDown、KeyUp、その他何をしていても、それを呼び出すことはありません...そして、ええ、私はそれらの使い方を知っています。
したがって、押されたキーをチェックできる関数がシステムにあれば、使用されたキーの配列などが返されます。正しい方向に向けられれば幸いです。
キーボードのすべてのキーの状態を照会したいようです。そのための最適な関数は 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.Control
Keys.Shift
Keys.ControlKey
Keys.LShiftKey
したがって、特定のキーが設定されているかどうかを確認するには、次のようにします。
var code = GetVirtualKeyCode(Key.A);
if ((array[code] & 0x80) != 0) {
// It's pressed
} else {
// It's not pressed
}
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);
アプリケーション内のどのコントロールにフォーカスがあるかに関係なく、アプリケーションがアクティブなときにすべてのキーストロークを知る必要がある場合はKeyPreview
、フォームのプロパティを使用できます。
プロパティをtrueに設定し、フォームで目的のキーイベントをサブスクライブするだけです。これで、具体的なコントロールに転送される前に、アプリケーション内のすべてのキーストロークを受け取ることができます。これにより、アプリケーションに反応し、Cancel
プロパティをtrueに設定してコントロールへの転送をキャンセルできます。
アプリケーションがアクティブでないときに押されたキーを受け取る必要がある場合は、ある種の低レベルのキーボードフックが必要です。私はそれをテストしませんでしたが、CodeProjectに関するこの記事はこの場合非常に有望に見えます。
そのフォーム内の別の子コントロールに現在フォーカスがある場合でも、フォームにフォーカスがあるときにキーが押されると発生するPreviewKeyDownイベントを探していると思います。