Глобальные события клавиатуры в приложениях Windows Store - программирование
Подтвердить что ты не робот

Глобальные события клавиатуры в приложениях Windows Store

Я работаю над игрой, Windows Store App, основанной на WPF и написанной на С#. Когда игрок нажимает клавишу Esc, я хочу приостановить игру и показать меню (Continue, Quit и т.д.).

Звучит просто. К сожалению, это не так.

Игра проходит в Windows.UI.Xaml.Controls.Page и в основном состоит из сотен Shape в Canvas, но ни одного Button, TextBox или всего остального, который поддерживает взаимодействие с клавиатурой. Единственное взаимодействие - щелкнуть или нарезать фигуры.

Мне нужно поймать события клавиатуры, глобально для всей страницы, независимо от того, какой элемент имеет фокус, или даже если есть какой-либо фокус на всех и т.д. Когда бы нажата клавиша Esc, событие должно срабатывать.

Что я пробовал:

  • Использование события Page.KeyDown или переопределение Page.OnKeyDown(KeyRoutedEventArgs e) (или KeyUp): не срабатывает, если нет элемента, такого как TextBox с фокусом клавиатуры. Но в моем пользовательском интерфейсе нет такого элемента.

  • Использование невидимого (Opacity = 0 и/или скрытого под Canvas) TextBox в качестве взлома для работы KeyDown: как только Canvas или любая Shape нажата/нажата, TextBox теряет фокус и взломать перестает работать. Таким образом, требуется больше хаков, чтобы заставить его держать фокус, который закручивает другие вещи, такие как кнопки меню. Более того, TextBox иногда показывает клавиатуру программного обеспечения Windows, что довольно нежелательно. Едва работающий, хрупкий хак.

  • Использование InputGestures, KeyBinding и т.д.: недоступно для приложений Windows Store.

Любые идеи или решения?

4b9b3361

Ответ 1

Попробуйте использовать CoreWindow.KeyDown. Назначьте обработчик на своей странице, и я считаю, что он должен перехватывать все события keydown.

public MyPage()
{
    CoreWindow.GetForCurrentThread().KeyDown += MyPage_KeyDown;
}

void MyPage_KeyDown(CoreWindow sender, KeyEventArgs args)
{
    Debug.WriteLine(args.VirtualKey.ToString());
}

Ответ 2

CoreWindow.GetForCurrentThread(). KeyDown не будет записывать события, если он сосредоточен на каком-то другом grid/webView/текстовом поле, поэтому вместо AcceleratorKeyActivated. Независимо от того, где основное внимание будет уделено, он всегда будет захватывать событие.

public MyPage()
{
    Window.Current.CoreWindow.Dispatcher.AcceleratorKeyActivated += AcceleratorKeyActivated;
}


private void AcceleratorKeyActivated(CoreDispatcher sender, AcceleratorKeyEventArgs args)
{
    if (args.EventType.ToString().Contains("Down"))
    {
        var ctrl = Window.Current.CoreWindow.GetKeyState(VirtualKey.Control);
        if (ctrl.HasFlag(CoreVirtualKeyStates.Down))
        {
            switch (args.VirtualKey)
            {
                case VirtualKey.A:
                    Debug.WriteLine(args.VirtualKey);
                    Play_click(sender, new RoutedEventArgs());
                    break;
            }
        }
    }
}