Как определить нажатую в данный момент клавишу?


на Windows Forms, вы можете узнать, в любое время, текущее положение курсора благодаря курсоры класса.

то же самое, кажется, не доступно для клавиатуры. Можно ли узнать, если, например,Shift клавиша нажата?

абсолютно ли необходимо отслеживать каждое уведомление клавиатуры (события KeyDown и KeyUp)?

11 121

11 ответов:

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

Это также будет верно, если Ctrl+Shift вниз. Если вы хотите проверить, нажата ли только Shift,

if (Control.ModifierKeys == Keys.Shift)

если вы находитесь в классе, который наследует Control (например, форма), вы можете удалить 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;
    }
}

вы также можете посмотреть на следующее, Если вы ссылаетесь на систему.Окна.Вход

if (Keyboard.Modifiers == ModifierKeys.Shift)

пространство имен клавиатуры также можно использовать для проверки состояния нажатия других клавиш с помощью клавиатуры.IsKeyDown (Key), или если вы подписываетесь на KeyDownEvent или подобное событие, аргументы события несут список нажатых в данный момент клавиш.

большинство из этих ответов либо слишком сложны, либо не работают для меня (например, система.Окна.Вход, кажется, не существует). Затем я нашел пример кода, который отлично работает: 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, можно использовать Keyboard.IsKeyDown метод из нового System.Windows.Input пространство имен. Например:

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

несмотря на то, что это часть WPF, этот метод отлично работает для приложений WinForm (при условии, что вы добавляете ссылки на PresentationCore.dll и WindowsBase.dll). К сожалению, однако, версии 3.0 и 3.5 Keyboard.IsKeyDown метод не работает для приложений WinForm. Поэтому, если вы хотите использовать это в приложении WinForm, вам нужно будет ориентироваться на .NET Framework 4.0 или более поздней версии для того, чтобы он работал.

вы можете P / Invoke вниз к Win32 GetAsyncKeyState для проверки любой клавиши на клавиатуре.

вы можете передавать значения из перечисления ключей (например, ключи.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 является свойством, а нажатие клавиши (например, щелчок мыши / mousemove) является событием. Обычно рекомендуется, чтобы интерфейс управлялся событиями. О единственный раз, когда вам понадобится выше, если вы пытаетесь сделать shift + mouseclick вещь.

лучший способ, который я нашел для управления вводом с клавиатуры в форме Windows Forms, - это обработать его после нажатия клавиши и до того, как сфокусированный элемент управления получит событие. Microsoft поддерживает встроенный Form - свойство уровня с именем .KeyPreview чтобы облегчить эту точную вещь:

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

затем события _keydown, _KeyPress и / или _KeyUp формы можно маршалировать для доступа к входным событиям до того, как сфокусированный элемент управления формой их увидит, и вы можете применить обработчик логика, чтобы захватить событие там или позволить ему пройти через сфокусированный элемент управления формой.

хотя и не так структурно изящно, как в XAML это!--10--> архитектура маршрутизации событий, это делает управление функциями уровня формы в Winforms намного проще. Смотрите MSDN примечания по KeyPreview для предостережения.

В WinForms:

if( Form.ModifierKeys == Keys.Shift )

это звучит как дубликат вопроса переполнения стека клавиша Detect Shift нажата без использования событий в Windows Forms?.