检测是否在C#中按下任何键(不是A,B,但是任何键)

时间:2009-11-17 23:04:11

标签: c# wpf input keyboard key

[编辑3] 使用“奇怪”版本时,我有点“解决了”。至少对于最重要的键。这对我的情况来说是足够的,我想检查ALT和ALT + A是不一样的(从而确保没有按下A)。不完美,但已经有很多时间来解决这么小的问题了。无论如何,谢谢你的所有答案...... [编辑3]

[编辑4]由于280Z28 [/编辑4]

解决了它更清洁

我知道如何检查修改键以及如何测试单个键。 问题是,我想检查是否按下了任何键。以下方法似乎“奇怪”: - )

用C#编写的WPF应用程序

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

我知道这是一个枚举,所以我想到了一个循环,但是使用的“最大数字”是什么。这可能吗?顺便说一句,这是一个非常特殊的情况,通常我会使用一个事件,但在这种情况下我必须这样做。不幸的是,没有“list”Keyboard.CurrentlyDownKeys。至少我没有看到它。

谢谢, 克里斯

编辑:好的,因为这似乎是一个更大的交易,这里的原因是: 我已经定义了一个“KeySet”,它用作自定义函数的DictionaryKey。如果有人点击某个元素,则包装器会遍历字典并检查是否有任何预定义的“Keysets”处于活动状态。

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

当前实现的唯一“问题”,如果我定义一个不包含任何REAL键的Keyset,如按下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;
    }
}

10 个答案:

答案 0 :(得分: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);
}

答案 1 :(得分:3)

使用XNA框架,您可以使用以下方法检查是否已按下任何键。

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

答案 2 :(得分:3)

相当古老的问题但是如果有人遇到这个并且不想使用外部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;
    }

您可以通过在函数外部执行枚举并保留列表以供稍后优化来进行优化。

答案 3 :(得分:0)

这段代码从哪里运行?它是在事件处理程序中吗?许多表单和控件将触发KeyPress事件以及KeyDown事件。您可能希望查看这些事件,并在其中一个事件发生时将其设置为true。您还必须听取相应的事件,告诉您何时释放密钥(KeyUp,我认为)。

答案 4 :(得分:0)

如果您使用的是Windows.Forms,请使用KeyDown事件,并使用相应的KeyEventArgs读出特定密钥。您可以访问KeyCode变量上的KeyEventArgs属性。

检查范围,例如A和Z之间:

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

答案 5 :(得分:0)

http://sourceforge.net/projects/keystate/显示“特殊”键。否则我认为你只需要监控它们。 SOUnds喜欢你想在全系统做这个吗?你想要完成什么?

答案 6 :(得分:0)

您可以为每个keydown事件递增计数器,并为每个keyup事件递减计数器。当计数器为零时,没有键被关闭。

答案 7 :(得分:0)

要检测按下哪个,您需要检查每个键状态,以及当前按下按下< / strong>。
记住:按下和向下键会有所不同。

    Public Sub Main()
        While True
            For i As Integer = 8 To 222
                Select Case i
                    Case 8, 13, 32, 48 To 57, 65 To 90, 186 To 192, 219 To 222
                        If GetAsyncKeyState(i) = -32767 And Not IsKeyDown(Keys.Control) Then
                            Console.Write(CodeToChar(i))
                        End If
            End Select
        Next
    End Sub
    
    Public Function IsKeyDown(Key As Keys) As Boolean
        Return (Control.ModifierKeys And Key) = Key
    End Function
    
    
    Function CodeToChar(i As Integer) As String
        Dim Character = Nothing
        IsShiftDown = IsKeyDown(Keys.Shift)
        If i > 64 And i < 91 Then c = If(Control.IsKeyLocked(Keys.CapsLock) Or IsShiftDown, Chr(i).ToString.ToUpper, Chr(i).ToString.ToLower) 
        If i = 8   Then Character = "[BACK]"
        If i = 13  Then Character = vbnewline
        If i = 32  Then Character = " "
        If i = 48  Then Character = If(IsShiftDown, ")", "0")
        If i = 49  Then Character = If(IsShiftDown, "!", "1")
        If i = 50  Then Character = If(IsShiftDown, "@", "2")
        If i = 51  Then Character = If(IsShiftDown, "#", "3")
        If i = 52  Then Character = If(IsShiftDown, "$", "4")
        If i = 53  Then Character = If(IsShiftDown, "%", "5")
        If i = 54  Then Character = If(IsShiftDown, "^", "6")
        If i = 55  Then Character = If(IsShiftDown, "&", "7")
        If i = 56  Then Character = If(IsShiftDown, "*", "8")
        If i = 57  Then Character = If(IsShiftDown, "(", "9")
        If i = 186 Then Character = If(IsShiftDown, ":", ";")
        If i = 187 Then Character = If(IsShiftDown, "+", "=")
        If i = 188 Then Character = If(IsShiftDown, "<", ",")
        If i = 189 Then Character = If(IsShiftDown, "_", "-")
        If i = 190 Then Character = If(IsShiftDown, ">", ".")
        If i = 191 Then Character = If(IsShiftDown, "?", "/")
        If i = 192 Then Character = If(IsShiftDown, "~", "`")
        If i = 219 Then Character = If(IsShiftDown, "{", "[")
        If i = 220 Then Character = If(IsShiftDown, "|", "\")
        If i = 221 Then Character = If(IsShiftDown, "}", "]")
        If i = 222 Then Character = If(IsShiftDown, """", "'")
        Return Character
    End Function

如果要使用c#版本,请转换here。 阅读keylogger代码以了解有关键状态的更多信息。

答案 8 :(得分:-1)

normally I would use an event

你应该仍然使用一个事件,最好是KeyDown,因为你不介意按下什么键,如果你是在windows上编程的话。如果没有,您可以使用类似 Console.ReadLine();

的内容

编辑:如果您正在寻找类似

的内容
if (Keyboard.IsKeyDown(Key.AnyKey)) return true;
那你一定是在开玩笑......

编辑2:嗯,你的记录器的方法很有趣,但我认为你正在重新发明轮子。当可以知道时,所有编程语言都提供了一些处理按键的方法。在C#for Windows中,这是使用事件完成的。此外,我认为你无法在.NET中自己处理这类事情,因为你需要从Win32 API访问一些系统函数,而AFAIK则不允许这样做(至少很容易。 ..)在托管代码中。一些解决方案是创建HOOK并从那里向您的应用程序发送消息,但我不知道如何在C#中执行此操作。这是德尔福的方式,我有更多的经验。

答案 9 :(得分:-1)

在键枚举中,枚举值为零(0),该值基本上测试“未按下任何键”,与“按下任何键”相反。因此,这样的事情可能会起作用;

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

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