获取按下的所有键
本文关键字:获取 | 更新日期: 2023-09-27 18:33:28
我必须使用什么才能获得当前按下的键盘上的"所有键"?因为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);
这将使用系统中每个虚拟键的 up/down 状态填充byte[]
。 如果设置了高位,则当前按下虚拟键。 将Key
映射到虚拟键代码只需考虑数字Key
值的byte
部分即可完成。
public static byte GetVirtualKeyCode(Key key) {
int value = (int)key;
return (byte)(value & 0xFF);
}
上述方法适用于大多数Key
值,但您需要小心修饰键。值Keys.Alt
、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 并在窗体上订阅所需的 Key 事件即可。现在,在将应用程序转发到具体控件之前,你将收到应用程序中的所有击键,从而允许您对它做出反应,并取消将其转发到控件,将 Cancel
属性设置为 true。
如果您需要在应用程序未处于活动状态时接收按下的键,则需要某种低级键盘挂钩。我没有测试它,但是这篇关于CodeProject的文章对于这种情况看起来很有希望。
我相信您正在寻找 PreviewKeyDown 事件,如果在窗体具有焦点时按下某个键,即使该窗体中的另一个子控件当前具有焦点,也会触发该事件。