2012-05-07 83 views
5

我必須使用什麼才能獲得此刻在鍵盤上按下的「所有鍵」?由於Form.KeyPress += new EventHandler()在充滿控件時並沒有多大作用。不管我做什麼,KeyDown,KeyUp或其他什麼都不叫它,是的,我知道如何使用它們。獲取所有按下的鍵

因此,如果系統中有任何功能可以檢查按下的按鍵,那麼將返回所使用的按鍵的數組或其他東西 - 我將不勝感激,指出正確的方向。

+1

你想,當你運行一段特定的代碼的所有按鍵按下,或者你想在你按下鍵時發生的事件? – zimdanen

+0

可能的重複[在winforms中實現鍵盤快捷鍵?](http://stackoverflow.com/questions/400113/best-way-to-implement-keyboard-shortcuts-in-winforms) –

+0

說我想要MouseWheel的事件處理程序,但我希望在執行EventHandler中的某些內容時按下「Ctrl」鍵。所以如果我滾動滾輪,我只能得到鼠標滾輪的結果,而不是按鍵。 – Deukalion

回答

12

這聽起來像你想查詢鍵盤中所有鍵的狀態。造成這種情況的最好的功能是Win32 API調用GetKeyboardState

我不相信存在着功能的一個很好的管理等同。它的PInvoke的代碼是相當直截了當

[DllImport("user32.dll")] 
[return: MarshalAs(UnmanagedType.Bool)] 
static extern bool GetKeyboardState(byte [] lpKeyState); 

var array = new byte[256]; 
GetKeyboardState(array); 

這將填充byte[]與系統中的每個虛擬鍵的上/下狀態。如果高位被設置,則虛擬鍵當前被按下。將Key映射到虛擬鍵碼是通過僅考慮數字Key值的byte部分來完成的。

public static byte GetVirtualKeyCode(Key key) { 
    int value = (int)key; 
    return (byte)(value & 0xFF); 
} 

上述工程大部分Key值的,但你必須要小心修飾鍵。值Keys.Alt,Keys.ControlKeys.Shift在這裏不起作用,因爲它們在技術上是修飾符而不是關鍵值。要使用修改器,你需要使用實際的相關鍵值Keys.ControlKeyKeys.LShiftKey,等...(真的沒有什麼東西,與主要結束)

所以,檢查如果特定的鍵設置可以做如下

var code = GetVirtualKeyCode(Key.A); 
if ((array[code] & 0x80) != 0) { 
    // It's pressed 
} else { 
    // It's not pressed 
} 
+0

它也適用於修改鍵,但是您必須使用Keys.AltKey,ShiftKey和ControlKey。 –

+0

@HansPassant良好的通話,忘記了那些條目 – JaredPar

+0

是的......但是之前沒有使用過這些東西的人可能會很好地包含我需要的命名空間,爲什麼DllImport顯示爲紅色,爲什麼GetKeyboardState不是無處可尋等等,等等......一半的答案意味着我必須搜索更多的答案等於沒有答案。 – Deukalion

0

我相信你正在尋找PreviewKeyDown事件,如果在表單有焦點的時候按下了一個鍵,即使當前表單中有另一個子控件有焦點,它也會觸發。

1

如果您只需要知道應用程序處於活動狀態時的所有按鍵,無論您的應用程序中哪個控件具有焦點,就可以使用表單的KeyPreview屬性。

只需將屬性設置爲true並訂閱表上所需的Key事件即可。現在,在將應用程序轉發到具體控件之前,您將收到所有擊鍵,允許您對自己做出反應並取消向控件的轉發,將Cancel屬性設置爲true。

如果您需要在應用程序不是活動應用程序時收到按下的按鍵,則需要某種低級別鍵盤掛鉤。我沒有測試,但this article on CodeProject看起來相當有希望的這種情況。

3

我已經在JaredPar的答案上擴展了一點點。下面的方法返回當前正在按下所有鍵的集合:

using System.Collections.Generic; 
using System.Linq; 
using System.Runtime.InteropServices; 
using System.Windows.Input; 

private static readonly byte[] DistinctVirtualKeys = Enumerable 
    .Range(0, 256) 
    .Select(KeyInterop.KeyFromVirtualKey) 
    .Where(item => item != Key.None) 
    .Distinct() 
    .Select(item => (byte)KeyInterop.VirtualKeyFromKey(item)) 
    .ToArray(); 

/// <summary> 
/// Gets all keys that are currently in the down state. 
/// </summary> 
/// <returns> 
/// A collection of all keys that are currently in the down state. 
/// </returns> 
public IEnumerable<Key> GetDownKeys() 
{ 
    var keyboardState = new byte[256]; 
    GetKeyboardState(keyboardState); 

    var downKeys = new List<Key>(); 
    for (var index = 0; index < DistinctVirtualKeys.Length; index++) 
    { 
     var virtualKey = DistinctVirtualKeys[index]; 
     if ((keyboardState[virtualKey] & 0x80) != 0) 
     { 
      downKeys.Add(KeyInterop.KeyFromVirtualKey(virtualKey)); 
     } 
    } 

    return downKeys; 
} 

[DllImport("user32.dll")] 
[return: MarshalAs(UnmanagedType.Bool)] 
private static extern bool GetKeyboardState(byte[] keyState); 
+0

我很難翻譯VB.Net中的DistinctVirtualKeys分配。你可以更好地評論它,也可以得到錯誤,沒有'.Select(KeyInterop.KeyFromVirtualKey)'的參數嗎? – beppe9000

相關問題