[C#] C # - проверить, нажата ли конкретная клавиша


Answers

Похоже, вы пытаетесь создать глобальную горячую клавишу в системе, и ваше приложение должно ответить, когда оно нажато.

Вам понадобятся две функции Win32 API RegisterHotKey и UnregisterHotKey .

Глядя на ваше using System.Windows.Input , похоже, вы пытаетесь сделать это с помощью WPF, что возможно.

Начнем с довольно простых P / Invokes:

using System.Runtime.InteropServices;

internal static class NativeMethods
{
    [DllImport("user32.dll")]
    public static extern bool RegisterHotKey(IntPtr windowHandle, int hotkeyId, uint modifierKeys, uint virtualKey);

    [DllImport("user32.dll")]
    public static extern bool UnregisterHotKey(IntPtr windowHandle, int hotkeyId);
}

Теперь, когда вы регистрируете свое Window , происходит то, что сообщение сообщения WM_HOTKEY отправляется на насос сообщений вашего приложения. Однако WPF абстрагирует это сообщение от вас, поэтому вам нужно добавить HwndSourceHook чтобы использовать его.

Как мы все это делаем? Начнем с инициализации нашего делегата HwndSourceHook . Добавьте этот фрагмент в свой MainWindow :

    using System.Windows.Interop;

    static readonly int MyHotKeyId = 0x3000;
    static readonly int WM_HOTKEY = 0x312;

    void InitializeHook()
    {
        var windowHelper = new WindowInteropHelper(this);
        var windowSource = HwndSource.FromHwnd(windowHelper.Handle);

        windowSource.AddHook(MessagePumpHook);
    }

    IntPtr MessagePumpHook(IntPtr handle, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
    {
        if (msg == WM_HOTKEY)
        {
            if ((int)wParam == MyHotKeyId)
            {
                // The hotkey has been pressed, do something!

                handled = true;
            }
        }

        return IntPtr.Zero;
    }

Хорошо, теперь у нас есть все, чтобы ответить на сообщение WM_HOTKEY . Однако нам нужно зарегистрировать нашу горячую клавишу! Давайте добавим еще несколько методов инициализации пары:

    void InitializeHotKey()
    {
        var windowHelper = new WindowInteropHelper(this);

        // You can specify modifiers such as SHIFT, ALT, CONTROL, and WIN.
        // Remember to use the bit-wise OR operator (|) to join multiple modifiers together.
        uint modifiers = (uint)ModifierKeys.None;

        // We need to convert the WPF Key enumeration into a virtual key for the Win32 API!
        uint virtualKey = (uint)KeyInterop.VirtualKeyFromKey(Key.A);

        NativeMethods.RegisterHotKey(windowHelper.Handle, MyHotKeyId, modifiers, virtualKey);
    }

    void UninitializeHotKey()
    {
        var windowHelper = new WindowInteropHelper(this);
        NativeMethods.UnregisterHotKey(windowHelper.Handle, MyHotKeyId);
    }

Хорошо! Где мы их помещаем? Не помещайте их в конструктор! Зачем? Потому что Handle будет 0 и недействителен! Поместите их здесь (в MainWindow ):

    protected override void OnSourceInitialized(EventArgs e)
    {
        base.OnSourceInitialized(e);
        InitializeHook();
        InitializeHotKey();
    }

Вы можете зарегистрировать несколько горячих клавиш, зарегистрировать и перерегистрировать новые. Это зависит от вас. Просто помните, что каждая горячая клавиша должна иметь уникальный идентификатор, зарегистрированный на нем. Это имеет смысл только потому, что ваш крюк для сообщения сообщения должен знать, какая горячая клавиша вызвала сообщение WM_HOTKEY !

Также хорошей практикой является отмена регистрации всех горячих клавиш, когда ваше приложение закрывается.

Question

Я новичок в программировании на C #. Я пытаюсь проверить, нажата ли клавиша, но я получаю следующее сообщение об ошибке: «Ошибка 1 Имя« Клавиатура »не существует в текущем контексте» «Ошибка 2 Имя« Ключ »не существует в текущем контексте «Можете ли вы рассказать мне, как это исправить?

//...
using System.Windows.Input;

class Main {
    public void Main() {
        while(true) {
            if(Keyboard.IsKeyPressed(Key.A)) {
                //...
            }
            return;
        }
    }
}