簡體   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