繁体   English   中英

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

[英]Detect if any key is pressed in C# (not A, B, but any)

[编辑 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;

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

谢谢,克里斯

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

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

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

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

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

使用 XNA 框架,您可以使用 thw follow 来检查是否按下了任何键。

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

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

要检查范围,请说在 A 和 Z 之间:

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

这段代码从哪里运行? 它在事件处理程序中吗? 许多窗体和控件将触发 KeyPress 事件以及 KeyDown 事件。 您可能需要查看这些事件,并在其中一个事件发生时将标志设置为 true。 您还必须监听相应的事件,该事件告诉您何时释放键(KeyUp,我认为也是如此)。

http://sourceforge.net/projects/keystate/显示“特殊”键。 否则我认为你只需要监视它们。 听起来您想在系统范围内执行此操作? 你想完成什么?

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

为了检测哪个按下,您需要检查每一个国家重点和关键,目前按下向下
请记住:按下和向下有区别。

    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# 版本,请在此处转换。 阅读键盘记录器代码以了解有关键状态的更多信息。

normally I would use an event

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

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

if (Keyboard.IsKeyDown(Key.AnyKey)) return true;

那你一定是在开玩笑……

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

在 Key Enumeration 中有一个 Enumeration 值 Zero(0),它基本上测试“No Key Pressed”,这与“Any key press”相反。 所以,这样的事情可能会奏效;

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

要么

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM