2009-07-08 4 views
121

В Windows Forms вы можете в любой момент узнать текущее положение курсора благодаря классу Cursors.Как определить текущую нажатую клавишу?

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

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

+0

Вы работаете в среде WPF или еще чего-нибудь еще? – epotter

+66

@epotter: Второе слово обозначает WinForms. –

ответ

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

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

if (Control.ModifierKeys == Keys.Shift) 

Если вы в классе, который наследуется Control (например, формы), вы можете удалить Control.

+5

Если я ничего не пропустил, вы не ответили на вопрос правильно. OP спрашивает обо всех ключах и использует клавишу Shift только в качестве примера. Итак, как вы обнаруживаете другие ключи, такие как от A до Z, от 0 до 9 и т. Д. – Ash

+2

Учитывая, что он принял ответ, кажется, что ему нужны только ключи-модификаторы. Если вам нужны другие ключи, вам нужно вызвать функцию API GetKeyState. – SLaks

+2

нет необходимости в GetKeyState. Вам просто нужно добавить фильтр сообщений. См. Мой ответ. – Ash

0

В WinForms:

if(Form.ModifierKeys == Keys.Shift) 

Это звучит как дубликат переполнением стека вопрос Detect Shift key is pressed without using events in Windows Forms?.

+0

Я не думаю, что это не сработает, если вы находитесь в текстовом поле – Joe

+0

Возможно, ему это неинтересно, но я просто хотел разобраться: p – Joe

8

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

К этой функции можно передать значения из перечисления клавиш (например, Keys.Shift), поэтому для его добавления требуется только несколько строк кода.

+0

«Клавиатура» не была распознана компилятором, но «GetAsyncKeystate» в user32 работал просто хорошо. Благодаря! –

+0

@ Эйнштейн: Рад помочь вам :-) –

22

Вы также можете посмотреть на следующем, если вы ссылаетесь System.Windows.Input

if (Keyboard.Modifiers == ModifierKeys.Shift) 

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

+1

На самом деле Keyboard.Modifiers не всегда работают правильно. Должен был найти трудный путь: http://discoveringdotnet.alexeyev.org/2008/09/keyboardmodifiers-sometimes-doesnt-work.html –

+0

За исключением того, что это не использует модификаторы форм, модификаторы System.Windows.Input - это другое пространство имен и работал отлично для нас каждый раз. –

2
if (Control.ModifierKeys == Keys.Shift) 
    //Shift is pressed 

от курсора х/y - свойство, а нажатие клавиши (например, щелчок мышью/mousemove) является событием. Лучшей практикой, как правило, является то, что интерфейс управляется событиями. Единственный раз, когда вам понадобится вышесказанное, - это если вы пытаетесь сделать вещь shift + mouseclick.

52

Код, приведенный ниже, заключается в том, как обнаружить почти все нажатые клавиши, а не только ключ 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; 
    } 
} 
+1

«GetKeyState» был бы более эффективным. Нет смысла отслеживать все ключи, когда Windows делает это за вас уже. – SLaks

+3

@ Пламя, если у вас нет контрольных данных, вы догадываетесь. Кроме того, GetKeyState сообщит вам состояние ключа, * если * вы можете поймать это событие клавиатуры в первую очередь. Мое прочтение вопроса заключается в том, что OP хочет знать, как получить состояние ключа в любое время *. Поэтому GetKeyState сам по себе бесполезен. – Ash

+0

Правильно. Я просто догадываюсь. – SLaks

2
if (Form.ModifierKeys == Keys.Shift) 

делает работу для текстового поля, если приведенный выше код в KeyDown событий формы и никакой другой элемент управления не захватывает KeyDown событие для ключа вниз.

Также один, возможно, пожелает прекратить дальнейшую ключевую обработку с:

e.Handled = true; 
5
if ((ModifierKeys == Keys.Control) && ((e.KeyChar & (char)Keys.F) != 0)) 
{ 
    // CTRL+F pressed ! 
} 
+1

мне очень помог. Спасибо –

2

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

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

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

Хотя это не так структурно изящно, как XAML's архитектура маршрутизации событий, это значительно упрощает управление функциями уровня на Winforms. См. MSDN notes on KeyPreview для оговорок.

15

Большинство из этих ответов слишком сложны или, похоже, не работают для меня (например, 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); 
    } 
    } 
} 
+3

'System.Windows.Input' существует; для других, борющихся с этим, вам нужно добавить ссылку на «PresentationCore» и дополнительную ссылку на «WindowsBase» для доступа к перечислению 'System.Windows.Input.Key'. Эта информация всегда может быть найдена в MSDN. – Alfie

+0

Этот класс должен быть 'static', а не' abstract'. – AbleArcher

+0

Ссылка не работает (404). –

10

С .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 или новее, чтобы он работал.

+0

просто примечание, это только для WPF. –

+2

@DiegoVieira На самом деле это не так. Функциональность была добавлена ​​как часть WPF, и для этого требуется, чтобы на эти библиотеки WPF ссылались, но метод Keyboard.IsKeyDown работает даже в проекте WinForm. –

+0

Действительно, вам нужно добавить PresentationCore.dll –

Смежные вопросы