Ускорение навигации в WinRT
87WinRT --- Ускорение навигации
Используете ли вы мышь с пятью кнопками вместо обычных трех? Я тоже не использую, но некоторые люди связали две дополнительные кнопки с командами перехода вперед и назад в Internet Explorer. Другие пользователи Internet Explorer привыкли выполнять переход вперед и назад комбинациями клавиш Att+<- и Att+->. На некоторых клавиатурах даже существуют специальные клавиши для выполнения этих операций. Возможно, вы захотите поддерживать те же комбинации клавиш для навигации в своих приложениях. Для этого понадобятся два события, которые нам ранее еще не встречались: PointerPressed и AcceleratorKeyActivated.
Событие AcceleratorKeyActivated недоступно в классах Page и Frame и даже в классе Window, встроенном в Frame. Зато оно доступно в CoreWindow - объекте, обеспечивающем получение событий ввода для Window, а вы можете получить объект CoreWindow для текущего объекта Window.
Обработчик AcceleratorKeyActivated первым получает доступ к нажатиям клавиш. Если нажатие будет идентифицировано как служебная комбинация клавиш, он может запретить дальнейшую обработку ввода приложением, задав свойству Handled в аргументах события значение true.
Событие PointerPressed инициируется по нажатию кнопки мыши или прикосновению к экрану пальцем или пером. Это событие определяется классом UIElement и наследуется классами Frame и Page, но обработчик этого события также можно определить и в CoreWindow.
Поскольку команды-ускорители от клавиатуры и мыши работают на более высоком уровне, чем страница, их обработку удобно разместить в классе App.
Ранее я приводил метод OnLaunched класса App из приложения ApplicationStateSave. Часть кода в конце метода была заменена многоточием. Рассмотрим этот код:
protected override void OnLaunched(LaunchActivatedEventArgs args)
{
// ...
// Добавленный код
Window.Current.CoreWindow.Dispatcher.AcceleratorKeyActivated
+= OnAcceleratorKeyActivated;
Window.Current.CoreWindow.PointerPressed += OnPointerPressed;
// Конец добавленного кода
}
Обработчик события PointerPressed проще, поэтому мы начнем с него. Состояния всех пяти кнопок мыши доступны в свойстве Properties свойства CurrentPoint аргументов события. Две дополнительные кнопки, обычно используемые для навигации, обозначаются XButton1 и XButton2. Нас интересуют только ситуации, в которых все обычные кнопки не нажаты, а нажата только одна из дополнительных кнопок - то есть их состояния отличны друг от друга:
private void OnPointerPressed(CoreWindow sender, PointerEventArgs args)
{
PointerPointProperties props = args.CurrentPoint.Properties;
if (!props.IsMiddleButtonPressed &&
!props.IsLeftButtonPressed &&
!props.IsRightButtonPressed &&
props.IsXButton1Pressed != props.IsXButton2Pressed)
{
if (props.IsXButton1Pressed)
GoBack();
else
GoForward();
args.Handled = true;
}
}
Если событие приводит к вызову метода GoBack или GoForward, обработчик события задает свойству Handled аргументов события значение true. Для ввода с клавиатуры обработчик события может использовать значения перечисления VirtualKey для клавиш <- и ->, но VirtualKey не содержит значений для специальных комбинаций клавиш браузеров. В Win32 API они идентифицируются именами VK_BROWSER_BACK и VK_BROWSER_FORWARD со значениями 166 и 167 соответственно:
private void OnAcceleratorKeyActivated(CoreDispatcher sender, AcceleratorKeyEventArgs args)
{
if ((args.EventType == CoreAcceleratorKeyEventType.KeyDown) ||
args.EventType == CoreAcceleratorKeyEventType.SystemKeyDown &&
(args.VirtualKey == VirtualKey.Left ||
args.VirtualKey == VirtualKey.Right ||
(int)args.VirtualKey == 166 ||
(int)args.VirtualKey == 167))
{
CoreWindow window = Window.Current.CoreWindow;
CoreVirtualKeyStates down = CoreVirtualKeyStates.Down;
// Игнорировать комбинации с нажатыми клавишами Shift или Ctrl
if ((window.GetKeyState(VirtualKey.Shift) & down) == down ||
(window.GetKeyState(VirtualKey.Control) & down) == down)
{
return;
}
// Получение состояния клавиши Alt
bool alt = (window.GetKeyState(VirtualKey.Menu) & down) == down;
// Переход назад по комбинации Alt+← или виртуальной клавише браузера
if (args.VirtualKey == VirtualKey.Left && alt ||
(int)args.VirtualKey == 166 && !alt)
{
GoBack();
args.Handled = true;
}
// Переход вперед по комбинации Alt+→ или виртуальной клавише браузера
if (args.VirtualKey == VirtualKey.Right && alt ||
(int)args.VirtualKey == 167 && !alt)
{
GoForward();
args.Handled = true;
}
}
}
Клавиши <- и -> используются для перехода только в том случае, если одновременно с ними нажата клавиша Alt, но не нажаты ни Shift, ни Ctrl, а специальные браузерные клавиши принимаются только при отсутствии нажатых клавиш-модификаторов.
Метод GetKeyState немного неудобен тем, что он может возвращать один из трех членов перечисления CoreVirtualKeyStates: None (0), Down (1) или Locked (2). Во внутренней реализации все клавиши рассматриваются как переключатели с двумя состояниями, а члены перечисления - как флаги. Не нажатая клавиша находится в исходном состоянии 0. При нажатии она переходит в состояние 3, а при отпускании - в состояние 2. Повторное нажатие вызывает переход в состояние 1, а отпускание возвращает клавишу в состояние 0.