c# - 检测是否在 C# 中按下了任何键(不是 A、B,而是任何键)

标签 c# wpf input keyboard key

[编辑 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。至少我没看到。

谢谢, 克里斯

编辑: 好的,因为这似乎是一件大事,原因如下: 我定义了一个“KeySet”作为自定义函数的 DictionaryKey。如果有人单击某个元素,包装器将遍历字典并检查是否有任何预定义的“键集”处于事件状态。

这让我可以定义简单的触发器,例如如果按下 ALT+A+B,则运行此函数。另一种选择是例如如果按下 ALT+STRG+A(在鼠标单击 WPF 元素期间),则运行此函数。

当前实现的唯一“问题”是,如果我定义一个不包含任何真实键的键集,比如在按下 ALT 时运行,如果按下 ALT+A 也会触发它。哦,写到这里,我意识到还有一个问题。如果按下 ALT+A+B+C,ALT+A+B 目前也会触发。

也许我的方法是错误的,我应该创建一个“静态键跟踪器”并将键集与其值(通过事件获取)进行比较。我会试一试。

编辑 2 这是行不通的,至少不是以一种简单的方式。我需要一个 FrameworkElement 附加到 KeyDown,但我没有在静态构造函数中使用它。而且我对某个元素的 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;
    }
}

最佳答案

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

关于c# - 检测是否在 C# 中按下了任何键(不是 A、B,而是任何键),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1752494/

相关文章:

c# - 如何在 ASP.NET 图表控件中显示值

c# - 是否可以从另一个线程修改内存 'unsafe' ly 中的 WPF BitmapSource

redirect - PowerShell 中 cmd 的输入重定向

java - 将用户输入分开并用循环填充(Java)

Eclipse 的 C# 插件

c# - 从 C# 使用 C++ 类

c# - 需要建议 : Switching from Linq to SQL to Entity Framework

c# - 将 child 添加到 UserControl

c# - 在 WPF C# 中删除命名行

javascript - INPUT TEXT 删除浏览器默认下拉菜单