首页 文章

如何检测当前按下的键?

提问于
浏览
121

Windows Forms中,由于Cursors类,您可以随时知道光标的当前位置 .

键盘似乎没有相同的功能 . 是否可以知道,例如,按下Shift键是否被按下?

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

11 回答

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

    如果Ctrl Shift关闭,这也将成立 . 如果要检查是否按下Shift,

    if (Control.ModifierKeys == Keys.Shift)
    

    如果您在继承 Control 的类(例如表单)中,则可以删除 Control.

  • 10

    下面的代码是如何检测几乎所有当前按下的键,而不仅仅是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;
        }
    }
    
  • 157

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

    if (Keyboard.Modifiers == ModifierKeys.Shift)
    

    Keyboard命名空间也可用于使用Keyboard.IsKeyDown(Key)检查其他键的按下状态,或者如果您订阅了KeyDownEvent或类似事件,则事件参数带有当前按下的键列表 .

  • 15

    这些答案中的大多数要么太复杂,要么似乎不存在 . 然后我发现了一些工作正常的示例代码: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);
        }
      }
    }
    
  • 5

    从.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或更高版本作为目标才能使用 .

  • 52

    您可以P/Invoke下载到Win32 GetAsyncKeyState来测试键盘上的任何键 .

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

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

    如果上面的代码在窗体的keydown事件中,并且没有其他控件捕获密钥关闭的keydown事件,则对文本框有用 .

    还有人可能希望停止进一步的密钥处理:

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

    光标x / y位置是属性,按键(如鼠标单击/鼠标移动)是一个事件 . 最佳做法通常是让界面成为事件驱动 . 关于你唯一需要上述的时间就是你要做一个移动鼠标点击的事情 .

  • 2

    我发现在Windows窗体表单上管理键盘输入的最佳方法是在击键后和聚焦控件接收事件之前处理它 . Microsoft维护一个名为 .KeyPreview 的内置 Form -level属性,以便于实现这一目标:

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

    然后可以封送表单的_KeyDown,_KeyPress和/或_KeyUp事件以在聚焦表单控件看到它们之前访问输入事件,并且可以应用处理程序逻辑来捕获事件或允许它传递到聚焦表单控件 .

    虽然不像XAML's事件路由体系结构那样结构优雅,但它使Winforms中的表单级函数管理变得更加简单 . 有关警告,请参阅MSDN notes on KeyPreview .

  • 22

    在WinForms中:

    if( Form.ModifierKeys == Keys.Shift )
    

    这听起来像Stack Overflow问题Detect Shift key is pressed without using events in Windows Forms?的重复 .

相关问题