2009-11-17 87 views
10

[編輯3] 我有種「解決它」在使用「奇怪的」版本。至少對於最重要的按鍵。這對我的情況很有幫助,我想檢查ALT和ALT + A是否不相同(從而確保A未被按下)。不完美,但已經花了很多時間處理這樣一個小問題。感謝反正... [編輯3]檢測是否有任何按鍵在C#(不是A,B,但任何)

[編輯4]解決它更清潔感謝280Z28 [/ EDIT 4]

我知道如何檢查修改鍵以及如何將所有的答案測試一個密鑰。 問題是,我想檢查是否有任何按鍵被按下。下面的方法似乎是「奇怪」 :-)

WPF在C#編寫

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

我知道這是一個枚舉應用程序,所以我想到了一個循環,但什麼是「最大號」使用。這可能嗎?順便說一句,它是一個非常特殊的情況,通常我會使用一個事件,但在這種情況下,我必須這樣做。不幸的是,沒有「列表」Keyboard.CurrentlyDownKeys。至少我沒有看到它。

謝謝, 克里斯

編輯:好的,因爲它似乎是一個更大的交易,在這裏這樣做的原因: 我已經定義了一個「密鑰集」充當DictionaryKey自定義功能。如果任何人點擊一個元素,包裝器遍歷字典並檢查是否有任何預定義的「Keysets」是活動的。

這使我可以定義簡單的觸發器,例如,如果按下ALT + A + B,則運行此功能。另一個選擇是例如如果按下ALT + STRG + A(在鼠標點擊WPF元素期間),請運行此功能。

當前實現的唯一「問題」,如果我定義不包含任何REAL鍵的鍵集,如按下ALT鍵時運行,如果按下ALT + A鍵,也會觸發它。哦,在寫這篇文章的時候,我意識到還有另外一個問題。如果按下ALT + A + B + C,ALT + A + B也會觸發。

也許我的方法是錯誤的,我應該創建一個「靜態鍵跟蹤器」,並將鍵集與它的值進行比較(通過事件獲得)。我會試試這個。

EDIT 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; 
    } 
} 
+2

你的應用程序是什麼?安慰? Windows窗體? WPF?網站? – jrista 2009-11-17 23:10:45

+0

請參閱標題... .NET C# – 2009-11-17 23:18:52

+0

這沒有幫助。 – 2009-11-17 23:22:44

回答

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

感謝您的努力,但我得到了「EntryPointNotFound」異常。可能是由於Windows 7的限制,不同的內核,不知道。另外,對於低級別(即使這將是唯一的方式)... – 2009-11-18 00:17:07

+0

@Christian:請注意,我最初有錯誤的導入指定 - 我把kernel32,但它應該是user32。 – 2009-11-18 00:45:54

+0

@Christian:另外,我在'AnyKeyPressed'中加了一個'Skip(8)',所以它不會因爲按下鼠標按鈕而返回true。 – 2009-11-18 00:46:48

0

在哪裏運行該代碼?它是否在事件處理程序中?許多窗體和控件都會觸發KeyPress事件以及KeyDown事件。您可能想要查看這些事件,並在發生其中一個事件時將其設置爲true。你還必須聽取相應的事件,告訴你密鑰何時被釋放(KeyUp,同樣,我認爲)。

0

如果您使用Windows.Forms,請使用KeyDown事件,並使用相應的KeyEventArgs讀出特定密鑰。您可以訪問KeyEventArgs變量上的KeyCode屬性。

要檢查的範圍,A和Z之間說:

if (e.KeyCode>=Keys.A && e.KeyCode<=Keys.Z) 
{ 
    // do stuff...or not 
}
-1
normally I would use an event 

你仍然應該使用的事件,最好的keydown因爲你不介意按什麼鍵,如果你是編程在窗戶上。如果沒有,你可以使用像Console.ReadLine();

編輯:如果您正在尋找類似

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

,那麼你一定是在開玩笑......

編輯2:那麼,你的記錄器的方法很有趣,但我認爲你正在重新發明輪子。所有的編程語言都提供了一些方法來處理按下的按鍵,當這可以被知道。在C#for Windows中,這是通過事件完成的。另外,我認爲你不能在.NET中自己處理這類事情,因爲你需要從Win32 API訪問一些系統函數,而且AFAIK不允許你這樣做(至少很容易。 ..)託管代碼。一些解決方案將創建一個HOOK並從那裏發送消息到您的應用程序,但我不知道如何在C#中執行此操作。德爾福就是這樣,我有更多的經驗。

+4

不是在開玩笑:-)但顯然是錯誤的思路。但我沒有發現它那麼遠。我的意思是爲什麼不,如果我想知道是否按下任何鍵,可能會出現這種情況。編輯條目,將嘗試可用於檢查的靜態「記錄器」... – 2009-11-17 23:28:43

+0

您可以使用WinForms或WPF中的KeyUp和KeyDown事件「發明」這種類型的鍵狀態 - 在按鍵上添加按下將鍵值添加到列表中,然後將其刪除 - 隨時可以檢查列表是否包含要查找的值,並且您將知道該鍵是否被按下。 – BrainSlugs83 2013-12-23 12:05:11

0

您可以爲每個keydown事件增加一個計數器,併爲每個keyup事件遞減計數器。當計數器爲零時,沒有按鍵關閉。

+0

不可能,KeyDown事件被某些WPF元素所佔用,而當按下A時我甚至可能不在我的應用程序中。然後我保留它,點擊我的應用程序,並且它不檢查A是否被按下... – 2009-11-17 23:38:06

+3

您正在看房子。一個人進去。一個人走了出去。一個人進去。一個人走了出去。一個人走出去。你從邏輯上得出關於這一系列觀察的結論是什麼? (1)房子裏有-1個人,或者(2)我開始觀看之前房子裏有人? – 2009-11-18 02:15:33

+1

@Eric:我會說,如果有人現在進去,房子就會變空。 – Zano 2010-02-18 14:14:59

3

使用XNA框架,您可以使用thw follow來檢查是否有任何按鍵被按下。

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

爲什麼任何用戶想要使用XNA框架來檢測他們的按鍵? XNA是一款專門用於視頻遊戲開發的胖客戶端 – Rockstart 2012-10-26 06:23:11

+2

也許是因爲OP的嘗試通常只在視頻遊戲中完成...... – BrainSlugs83 2013-12-23 12:06:39

2

相當一個老問題,但萬一有人遇到這一點,不希望使用外部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; 
    } 

您可以通過在函數之外進行枚舉並稍後保留列表來優化這一點。

相關問題