Определите, нажата ли какая-либо клавиша в C# (не A, B, но любая)

[правка 3] Я бы "решали" по по "странной" версии. По крайней мере, для самых важных ключей. Этого достаточно для моего случая, когда я хочу проверить, что ALT и ALT+A не одинаковы (тем самым убедившись, что A не нажата). Не идеально, но уже много времени, для такой маленькой проблемы. В любом случае, спасибо за ответы... [EDIT 3]

[EDIT 4] решил его намного чище благодаря 280Z28 [/EDIT 4]

Я знаю, как проверить клавиш-модификаторов и как проверить на наличие одного ключа. Проблема в том, что я хочу проверить, нажата ли какая-либо клавиша. Следующий подход кажется "странным" :-)

приложение WPF, написанное на C#

if (Keyboard.IsKeyDown(Key.A)) return true;
if (Keyboard.IsKeyDown(Key.B)) return true;
if (Keyboard.IsKeyDown(Key.C)) return true;

Я знаю, что это перечисление, поэтому я подумал о цикле, но какое "самое большое число" использовать. И возможно ли это? кстати, это очень особый случай, обычно я бы использовал событие, но в этом случае я должен сделать это таким образом. Unfortunatily, нет "списка" Клавиатура.CurrentlyDownKeys. По крайней мере, я его не видел.

спасибо, Крис!--3-->

EDIT: хорошо, потому что это кажется большим делом, вот причина этого: Я определил "набор ключей", который служит DictionaryKey для пользовательских функций. Если кто-то нажимает на элемент, оболочка выполняет итерацию по словарю и проверяет, активен ли какой-либо из предопределенных "наборов ключей".

Это позволяет мне определить простые триггеры, например, запустить эту функцию, если Alt+A + B нажата. Другой вариант, например, запустить эту функцию, если Alt+STRG + a нажата (во время щелчка мыши на элементе WPF).

единственная "проблема" с текущей реализацией, если я определяю набор ключей, который не содержит никаких реальных ключей, например run, если нажат ALT, он также запускается, если нажат ALT+A. О, когда я пишу это, я понимаю, что есть еще одна проблема. ALT+A+B в настоящее время также срабатывает при нажатии ALT+A+B+C.

возможно, мой подход неправильный, и я должен создать "статический трекер ключей" и сравнить набор ключей с его значениями (полученными через события).. Я попробую.

Изменить 2 Это не работает, по крайней мере, не простым способом. Мне нужен FrameworkElement для присоединения к KeyDown, но у меня его нет в статическом конструкторе. И меня интересуют не KeyDownEvents определенного элемента, а"глобально"...Я думаю, что я откладываю эту проблему, это не так важно. Тем не менее, если кто-нибудь знает лучше различный подход...

так долго, для всех, кто заботится, вот какой-то код:

    public class KeyModifierSet
{
    internal readonly HashSet<Key> Keys = new HashSet<Key>();
    internal readonly HashSet<ModifierKeys> MKeys = new HashSet<ModifierKeys>();

    public override int GetHashCode()
    {
        int hash = Keys.Count + MKeys.Count;
        foreach (var t in Keys)
        {
            hash *= 17;
            hash = hash + t.GetHashCode();
        }
        foreach (var t in MKeys)
        {
            hash *= 19;
            hash = hash + t.GetHashCode();
        }
        return hash;
    }

    public override bool Equals(object obj)
    {
        return Equals(obj as KeyModifierSet);
    }
    public bool Equals(KeyModifierSet other)
    {
        // Check for null
        if (ReferenceEquals(other, null))
            return false;

        // Check for same reference
        if (ReferenceEquals(this, other))
            return true;

        // Check for same Id and same Values
        return Keys.SetEquals(other.Keys) && MKeys.SetEquals(other.MKeys);
    }

    public bool IsActive()
    {
        foreach (var k in Keys)
            if (Keyboard.IsKeyUp(k)) return false;

        if ((Keys.Count == 0) && !Keyboard.IsKeyDown(Key.None)) return false;


        foreach (var k in MKeys)
            if ((Keyboard.Modifiers & k) == 0) return false;

        if ((MKeys.Count == 0) && Keyboard.Modifiers > 0) return false;

        return true;
    }


    public KeyModifierSet(ModifierKeys mKey)
    {
        MKeys.Add(mKey);
    }
    public KeyModifierSet()
    {

    }
    public KeyModifierSet(Key key)
    {
        Keys.Add(key);
    }
    public KeyModifierSet(Key key, ModifierKeys mKey)
    {
        Keys.Add(key);
        MKeys.Add(mKey);
    }
    public KeyModifierSet Add(Key key)
    {
        Keys.Add(key);
        return this;
    }
    public KeyModifierSet Add(ModifierKeys key)
    {
        MKeys.Add(key);
        return this;
    }
}

8 ответов


[DllImport("user32.dll", EntryPoint = "GetKeyboardState", SetLastError = true)]
private static extern bool NativeGetKeyboardState([Out] byte[] keyStates);

private static bool GetKeyboardState(byte[] keyStates)
{
    if (keyStates == null)
        throw new ArgumentNullException("keyState");
    if (keyStates.Length != 256)
        throw new ArgumentException("The buffer must be 256 bytes long.", "keyState");
    return NativeGetKeyboardState(keyStates);
}

private static byte[] GetKeyboardState()
{
    byte[] keyStates = new byte[256];
    if (!GetKeyboardState(keyStates))
        throw new Win32Exception(Marshal.GetLastWin32Error());
    return keyStates;
}

private static bool AnyKeyPressed()
{
    byte[] keyState = GetKeyboardState();
    // skip the mouse buttons
    return keyState.Skip(8).Any(state => (state & 0x80) != 0);
}

используя структуру XNA, вы можете использовать THW follow для проверки, была ли нажата какая-либо клавиша.

Keyboard.GetState().GetPressedKeys().Length > 0

довольно старый вопрос, но в случае, если кто-то сталкивается с этим и не хочет использовать внешние dll, вы можете просто перечислить возможные ключи и цикл над ними.

    bool IsAnyKeyPressed()
    {
        var allPossibleKeys = Enum.GetValues(typeof(Key));
        bool results = false;
        foreach (var currentKey in allPossibleKeys)
        {
            Key key = (Key)currentKey;
            if (key != Key.None)
                if (Keyboard.IsKeyDown((Key)currentKey)) { results = true; break; }
        }
        return results;
    }

вы можете немного оптимизировать это, выполнив перечисление за пределами функции и сохранив список на потом.


откуда этот код работает? Это в обработчике событий? Многие формы и элементы управления будут запускать событие нажатия клавиши, а также событие KeyDown. Вы можете просмотреть эти события и установить флаг true, когда происходит одно из них. Вам также придется слушать соответствующее событие, которое говорит вам, когда ключ выпущен (KeyUp, также, я думаю).


если вы используете Windows.Forms используйте KeyDown событие и считывание определенного ключа с помощью соответствующего KeyEventArgs. Вы можете получить доступ к KeyCode собственности на KeyEventArgs переменной.

чтобы проверить диапазоны, скажем, между A и Z:

if (e.KeyCode>=Keys.A && e.KeyCode<=Keys.Z)
{
  // do stuff...or not
}

http://sourceforge.net/projects/keystate/ показывает "специальные" клавиши. В противном случае, я думаю, вам просто придется следить за ними. Похоже, ты хочешь сделать это по всей системе? Чего ты пытаешься добиться?


вы можете увеличить счетчик для каждого события keydown и уменьшить его для каждого события keyup. Когда счетчик равен нулю, клавиши не опущены.


normally I would use an event

вы все равно должны использовать событие, предпочтительно KeyDown, так как вы не возражаете, какая клавиша нажата, если вы программируете на windows. Если нет, вы можете использовать что-то вроде