如何检测当前按下的按键?

在Windows窗体中 ,您可以随时了解Cursors类的当前位置。

同样的事情似乎没有可用的键盘。 是否有可能知道,例如,按下Shift键?

是否有必要追查每一个键盘通知(KeyDown和KeyUp事件)?

if ((Control.ModifierKeys & Keys.Shift) != 0) 

如果Ctrl + Shiftclosures,这也将是真实的。 如果你想检查是否单独按下Shift,

 if (Control.ModifierKeys == Keys.Shift) 

如果您在inheritanceControl (如窗体)的类中,则可以删除该Control.

下面的代码是如何检测几乎所有当前按下的键,而不仅仅是Shift键。

 private KeyMessageFilter m_filter = new KeyMessageFilter(); private void Form1_Load(object sender, EventArgs e) { Application.AddMessageFilter(m_filter); } public class KeyMessageFilter : IMessageFilter { private const int WM_KEYDOWN = 0x0100; private const int WM_KEYUP = 0x0101; private bool m_keyPressed = false; private Dictionary<Keys, bool> m_keyTable = new Dictionary<Keys, bool>(); public Dictionary<Keys, bool> KeyTable { get { return m_keyTable; } private set { m_keyTable = value; } } public bool IsKeyPressed() { return m_keyPressed; } public bool IsKeyPressed(Keys k) { bool pressed = false; if (KeyTable.TryGetValue(k, out pressed)) { return pressed; } return false; } public bool PreFilterMessage(ref Message m) { if (m.Msg == WM_KEYDOWN) { KeyTable[(Keys)m.WParam] = true; m_keyPressed = true; } if (m.Msg == WM_KEYUP) { KeyTable[(Keys)m.WParam] = false; m_keyPressed = false; } return false; } } 

如果您引用System.Windows.Input,还可以查看以下内容

 if (Keyboard.Modifiers == ModifierKeys.Shift) 

键盘命名空间也可以用来检查其他键的按下状态是否与Keyboard.IsKeyDown(Key)一样,或者如果你正在订阅一个KeyDownEvent或者类似的事件,那么事件参数携带一个当前被按下的键的列表。

大多数这些答案要么太复杂,要么似乎不适合我(例如System.Windows.Input似乎不存在)。 然后我发现一些示例代码工作正常: http : //www.switchonthecode.com/tutorials/winforms-accessing-mouse-and-keyboard-state

如果页面在将来消失,我在下面发布相关的源代码:

 using System; using System.Windows.Forms; using System.Runtime.InteropServices; namespace MouseKeyboardStateTest { public abstract class Keyboard { [Flags] private enum KeyStates { None = 0, Down = 1, Toggled = 2 } [DllImport("user32.dll", CharSet = CharSet.Auto, ExactSpelling = true)] private static extern short GetKeyState(int keyCode); private static KeyStates GetKeyState(Keys key) { KeyStates state = KeyStates.None; short retVal = GetKeyState((int)key); //If the high-order bit is 1, the key is down //otherwise, it is up. if ((retVal & 0x8000) == 0x8000) state |= KeyStates.Down; //If the low-order bit is 1, the key is toggled. if ((retVal & 1) == 1) state |= KeyStates.Toggled; return state; } public static bool IsKeyDown(Keys key) { return KeyStates.Down == (GetKeyState(key) & KeyStates.Down); } public static bool IsKeyToggled(Keys key) { return KeyStates.Toggled == (GetKeyState(key) & KeyStates.Toggled); } } } 

自.NET Framework 3.0版以来,可以使用新的System.Windows.Input命名空间中的Keyboard.IsKeyDown方法。 例如:

 if (((Keyboard.IsKeyDown(Key.LeftCtrl) || Keyboard.IsKeyDown(Key.RightCtrl)) && Keyboard.IsKeyDown(Key.F)) { // CTRL + F is currently pressed } 

即使它是WPF的一部分,该方法适用于WinForm应用程序(只要您添加对PresentationCore.dllWindowsBase.dll的引用)。 但是,不幸的是, Keyboard.IsKeyDown方法的3.0和3.5版本不适用于WinForm应用程序。 因此,如果您想在WinForm应用程序中使用它,则需要将其定位到.NET Framework 4.0或更高版本才能运行。

您可以P / Invoke到Win32 GetAsyncKeyState来testing键盘上的任何键。

您可以将Keys枚举(例如Keys.Shift)中的值传递给此函数,因此只需要添加几行代码即可。

 if ((ModifierKeys == Keys.Control) && ((e.KeyChar & (char)Keys.F) != 0)) { // CTRL+F pressed ! } 
 if (Form.ModifierKeys == Keys.Shift) 

如果上面的代码是在窗体的keydown事件中,并且其他控件没有捕获到按键的keydown事件,那么它就可以用于文本框。

也有人可能希望停止进一步的关键处理:

 e.Handled = true; 
 if (Control.ModifierKeys == Keys.Shift) //Shift is pressed 

游标的x / y位置是一个属性,按键(如鼠标点击/鼠标移动)是一个事件。 最佳实践通常是让界面事件驱动。 关于唯一一次你需要上述的是如果你正在尝试做shift + mouseclick的事情。

我发现在Windows窗体窗体上pipe理键盘input的最好方法是在按键之后和聚焦控件接收事件之前处理它。 Microsoft维护一个名为.KeyPreview的内置Form -level属性以便于实现这一点:

 public frmForm() { // ... frmForm.KeyPreview = true; // ... } 

然后,表单的_KeyDown,_KeyPress和/或_KeyUp事件可以在聚焦的表单控件看到它们之前被编组,以便访问input事件,并且可以应用处理程序逻辑来捕获那里的事件,或者允许它通过聚焦的表单控件。

虽然不像XAML的事件路由架构那样结构优雅,但它使Winforms中的表单级函数的pipe理更为简单。 有关注意事项,请参阅KeyPreview上的MSDN注释 。

在WinForms中:

 if( Form.ModifierKeys == Keys.Shift ) 

这听起来像堆栈溢出问题的重复检测按住Shift键而不使用Windows窗体中的事件?