Примечание.
Для доступа к этой странице требуется авторизация. Вы можете попробовать войти или изменить каталоги.
Для доступа к этой странице требуется авторизация. Вы можете попробовать изменить каталоги.
События клавиатуры и фокус
Следующие события клавиатуры могут возникать как для аппаратных, так и сенсорных клавиатур.
| Event | Description |
|---|---|
| KeyDown | Вызывается при нажатии клавиши. |
| KeyUp | Вызывается при отпускании клавиши. |
Это важно
Некоторые элементы управления XAML обрабатывают события ввода внутри системы. В этих случаях может показаться, что событие ввода не возникает, поскольку прослушиватель событий не вызывает соответствующий обработчик. Как правило, это подмножество клавиш обрабатывается обработчиком класса, чтобы обеспечить встроенную поддержку базовых возможностей доступа с клавиатуры. Например, класс Button переопределяет события OnKeyDown для ключа Пробела и клавиши ВВОД (а также OnPointerPressed) и направляет их в событие Click элемента управления. Когда нажатие клавиши обрабатывается классом элемента управления, события KeyDown и KeyUp не вызываются.
Это обеспечивает встроенный эквивалент клавиатуры для вызова кнопки, аналогично нажатию кнопки пальцем или щелчком мыши. Клавиши, кроме пробела и Enter, по-прежнему вызывают события KeyDown и KeyUp. Дополнительные сведения о том, как работает обработка событий на основе классов (в частности, в разделе "Обработчики событий ввода в элементах управления"), см. в разделе "События и перенаправленные события".
Элементы управления в вашем пользовательском интерфейсе генерируют события клавиатуры, только когда у них есть фокус ввода. Отдельный элемент управления получает фокус, когда пользователь щелкает или касается этого элемента управления непосредственно в макете или использует клавишу TAB для перехода в последовательность вкладок в области содержимого.
Вы также можете вызвать метод Focus элемента управления, чтобы принудительно установить фокус. Это необходимо при реализации сочетаний клавиш, так как фокус клавиатуры не задан по умолчанию при загрузке пользовательского интерфейса. Дополнительные сведения см. далее в этом разделе, в примере сочетаний клавиш.
Чтобы элемент управления мог получить фокус ввода, он должен быть включён, видим, а значения свойств IsTabStop и HitTestVisible должны быть равны true. Это состояние по умолчанию для большинства элементов управления. Если элемент управления имеет фокус ввода, он может вызывать и реагировать на события ввода клавиатуры, как описано далее в этом разделе. Вы также можете реагировать на получение или потерю фокуса элементом управления, обрабатывая события GotFocus и LostFocus.
По умолчанию последовательность вкладок элементов управления — это порядок, в котором они отображаются на языке разметки расширяемых приложений (XAML). Однако этот порядок можно изменить с помощью свойства TabIndex. Дополнительные сведения см. в разделе "Реализация специальных возможностей клавиатуры".
Обработчики событий клавиатуры
Обработчик событий ввода реализует делегат, предоставляющий следующие сведения:
- Отправитель события. Отправитель указывает объект, к которому привязан обработчик события.
- Данные события. Для событий клавиатуры эти данные будут экземпляром типа KeyRoutedEventArgs. Делегатом для обработчиков является KeyEventHandler. Наиболее релевантными свойствами KeyRoutedEventArgs для большинства сценариев обработчика являются Ключ и, возможно, KeyStatus.
- OriginalSource. Поскольку события клавиатуры являются маршрутизируемыми событиями, данные о событии содержат OriginalSource. Если вы намеренно разрешаете событиям пузыриться через дерево объектов, OriginalSource иногда является объектом озабоченности, а не отправителем. Однако это зависит от вашего дизайна. Дополнительные сведения о том, как использовать OriginalSource вместо отправителя, см. в разделе "Маршрутизируемые события клавиатуры" этой темы или в разделе «Общие сведения о событиях и маршрутизируемых событиях».
Присоединение обработчика событий клавиатуры
Вы можете подключить функции обработчика событий клавиатуры для любого объекта, включающего событие в качестве члена. Это включает любой производный класс UIElement . В следующем примере XAML показано, как присоединить обработчики к событию KeyUp для элемента Grid.
<Grid KeyUp="Grid_KeyUp">
...
</Grid>
Вы также можете подключить обработчик событий в коде. Дополнительные сведения см. в разделе "События" и обзор перенаправленных событий.
Определение обработчика событий клавиатуры
В следующем примере показано неполное определение обработчика событий KeyUp, присоединенного в предыдущем примере.
void Grid_KeyUp(object sender, KeyRoutedEventArgs e)
{
//handling code here
}
Private Sub Grid_KeyUp(ByVal sender As Object, ByVal e As KeyRoutedEventArgs)
' handling code here
End Sub
void MyProject::MainPage::Grid_KeyUp(
Platform::Object^ sender,
Windows::UI::Xaml::Input::KeyRoutedEventArgs^ e)
{
//handling code here
}
Использование KeyRoutedEventArgs
Все события клавиатуры используют KeyRoutedEventArgs для данных событий, а KeyRoutedEventArgs содержит следующие свойства:
Виртуальные ключи
Событие KeyDown возникает при нажатии клавиши. Аналогичным образом событие KeyUp генерируется, если клавиша отпущена. Обычно вы прослушиваете события для обработки определенного значения ключа. Чтобы определить, какой ключ нажимается или освобождается, проверьте значение ключа в данных события. Key возвращает значение типа VirtualKey. Перечисление VirtualKey включает все поддерживаемые ключи.
Модифицирующие клавиши
Клавиши-модификаторы — это такие клавиши, как CTRL или SHIFT, которые пользователи обычно нажимают в сочетании с другими ключами. Приложение может использовать эти сочетания в качестве пользовательских сочетаний клавиш для вызова команд приложения.
Замечание
Встроенные сочетания клавиш см. в разделе "Ключи доступа" и акселераторы клавиатуры.
Сочетания клавиш можно определить в обработчиках событий KeyDown и KeyUp. Когда возникает событие клавиатуры для клавиши, не являющейся клавишей-модификатором, после этого можно проверить, находится ли клавиша-модификатор в нажатом состоянии.
Кроме того, в WinUI 3 можно использовать InputKeyboardSource.GetKeyStateForCurrentThread для проверки состояния модификатора при нажатии клавиши без модификатора.
В следующих примерах реализуется этот второй метод, и также включается код-заглушка для первой реализации.
Замечание
Клавиша ALT представлена значением VirtualKey.Menu .
Пример сочетаний клавиш
В следующем примере показано, как реализовать набор пользовательских сочетаний клавиш. В этом примере пользователи могут управлять воспроизведением мультимедиа с помощью кнопок воспроизведения, приостановки и остановки или клавиш CTRL+P, CTRL+A и сочетаний клавиш CTRL+S. XAML-разметка кнопки отображает сочетания клавиш с помощью всплывающих подсказок и свойств AutomationProperties в надписях кнопок. Эта самостоятельная документация важна для повышения удобства использования и специальных возможностей приложения. Дополнительные сведения см. в разделе "Специальные возможности клавиатуры".
Обратите внимание также, что при загрузке страница задает фокус ввода для себя. Без этого шага элемент управления не имеет начального фокуса ввода, и приложение не вызывает входные события до тех пор, пока пользователь не задает фокус ввода вручную (например, путем вкладки или щелчка элемента управления).
<Grid KeyDown="Grid_KeyDown">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<MediaElement x:Name="DemoMovie" Source="xbox.wmv"
Width="500" Height="500" Margin="20" HorizontalAlignment="Center" />
<StackPanel Grid.Row="1" Margin="10"
Orientation="Horizontal" HorizontalAlignment="Center">
<Button x:Name="PlayButton" Click="MediaButton_Click"
ToolTipService.ToolTip="Shortcut key: Ctrl+P"
AutomationProperties.AcceleratorKey="Control P">
<TextBlock>Play</TextBlock>
</Button>
<Button x:Name="PauseButton" Click="MediaButton_Click"
ToolTipService.ToolTip="Shortcut key: Ctrl+A"
AutomationProperties.AcceleratorKey="Control A">
<TextBlock>Pause</TextBlock>
</Button>
<Button x:Name="StopButton" Click="MediaButton_Click"
ToolTipService.ToolTip="Shortcut key: Ctrl+S"
AutomationProperties.AcceleratorKey="Control S">
<TextBlock>Stop</TextBlock>
</Button>
</StackPanel>
</Grid>
//showing implementations but not header definitions
void MainPage::OnNavigatedTo(NavigationEventArgs^ e)
{
(void) e; // Unused parameter
this->Loaded+=ref new RoutedEventHandler(this,&MainPage::ProgrammaticFocus);
}
void MainPage::ProgrammaticFocus(Object^ sender, RoutedEventArgs^ e)
{
this->Focus(Windows::UI::Xaml::FocusState::Programmatic);
}
void KeyboardSupport::MainPage::MediaButton_Click(Platform::Object^ sender, Windows::UI::Xaml::RoutedEventArgs^ e)
{
FrameworkElement^ fe = safe_cast<FrameworkElement^>(sender);
if (fe->Name == "PlayButton") {DemoMovie->Play();}
if (fe->Name == "PauseButton") {DemoMovie->Pause();}
if (fe->Name == "StopButton") {DemoMovie->Stop();}
}
bool KeyboardSupport::MainPage::IsCtrlKeyPressed()
{
auto ctrlState = Microsoft::UI::Input::InputKeyboardSource::GetKeyStateForCurrentThread(VirtualKey::Control);
return (ctrlState & CoreVirtualKeyStates::Down) == CoreVirtualKeyStates::Down;
}
void KeyboardSupport::MainPage::Grid_KeyDown(Platform::Object^ sender, Windows::UI::Xaml::Input::KeyRoutedEventArgs^ e)
{
if (e->Key == VirtualKey::Control) isCtrlKeyPressed = true;
}
void KeyboardSupport::MainPage::Grid_KeyUp(Platform::Object^ sender, Windows::UI::Xaml::Input::KeyRoutedEventArgs^ e)
{
if (IsCtrlKeyPressed())
{
if (e->Key==VirtualKey::P) { DemoMovie->Play(); }
if (e->Key==VirtualKey::A) { DemoMovie->Pause(); }
if (e->Key==VirtualKey::S) { DemoMovie->Stop(); }
}
}
protected override void OnNavigatedTo(NavigationEventArgs e)
{
// Set the input focus to ensure that keyboard events are raised.
this.Loaded += delegate { this.Focus(FocusState.Programmatic); };
}
private void MediaButton_Click(object sender, RoutedEventArgs e)
{
switch ((sender as Button).Name)
{
case "PlayButton": DemoMovie.Play(); break;
case "PauseButton": DemoMovie.Pause(); break;
case "StopButton": DemoMovie.Stop(); break;
}
}
private static bool IsCtrlKeyPressed()
{
var ctrlState = Microsoft.UI.Input.InputKeyboardSource.GetKeyStateForCurrentThread(VirtualKey.Control);
return (ctrlState & CoreVirtualKeyStates.Down) == CoreVirtualKeyStates.Down;
}
private void Grid_KeyDown(object sender, KeyRoutedEventArgs e)
{
if (IsCtrlKeyPressed())
{
switch (e.Key)
{
case VirtualKey.P: DemoMovie.Play(); break;
case VirtualKey.A: DemoMovie.Pause(); break;
case VirtualKey.S: DemoMovie.Stop(); break;
}
}
}
Private isCtrlKeyPressed As Boolean
Protected Overrides Sub OnNavigatedTo(e As Navigation.NavigationEventArgs)
End Sub
Private Function IsCtrlKeyPressed As Boolean
Dim ctrlState As CoreVirtualKeyStates = Microsoft.UI.Input.InputKeyboardSource.GetKeyStateForCurrentThread(VirtualKey.Control);
Return (ctrlState & CoreVirtualKeyStates.Down) == CoreVirtualKeyStates.Down;
End Function
Private Sub Grid_KeyDown(sender As Object, e As KeyRoutedEventArgs)
If IsCtrlKeyPressed() Then
Select Case e.Key
Case Windows.System.VirtualKey.P
DemoMovie.Play()
Case Windows.System.VirtualKey.A
DemoMovie.Pause()
Case Windows.System.VirtualKey.S
DemoMovie.Stop()
End Select
End If
End Sub
Private Sub MediaButton_Click(sender As Object, e As RoutedEventArgs)
Dim fe As FrameworkElement = CType(sender, FrameworkElement)
Select Case fe.Name
Case "PlayButton"
DemoMovie.Play()
Case "PauseButton"
DemoMovie.Pause()
Case "StopButton"
DemoMovie.Stop()
End Select
End Sub
Замечание
Параметр AutomationProperties.AcceleratorKey или AutomationProperties.AccessKey в XAML предоставляет строковые сведения, которые документируют сочетания клавиш для вызова конкретного действия. Информация считывается клиентами Microsoft модель автоматизации пользовательского интерфейса, такими как Экранный диктор, и обычно напрямую предоставляется пользователю.
Настройка AutomationProperties.AcceleratorKey или AutomationProperties.AccessKey не имеет никаких действий самостоятельно. Чтобы фактически реализовать обработку сочетания клавиш в приложении, вам всё равно потребуется привязать обработчики событий KeyDown или KeyUp. Кроме того, подчёркивание текста для клавиши доступа не добавляется автоматически. Необходимо явно подчеркнуть текст для определённой клавиши в мнемонике с помощью встроенного форматирования Подчёркивание, если вы хотите отобразить подчёркнутый текст в интерфейсе.
Перенаправленные события клавиатуры
Некоторые события являются маршрутизируемыми событиями, включая KeyDown и KeyUp. Перенаправленные события используют стратегию маршрутизации пузырьков. Стратегия маршрутизации пузырьков означает, что событие происходит из дочернего объекта и затем направляется к последовательным родительским объектам в дереве объектов. Это дает еще одну возможность обрабатывать то же событие и взаимодействовать с теми же данными событий.
Рассмотрим следующий пример XAML, который обрабатывает события KeyUp для Canvas и двух объектов Button. В этом случае, если вы отпускаете клавишу, когда один из объектов Button удерживает фокус, генерируется событие KeyUp. Затем событие пузырится до родительского холста.
<StackPanel KeyUp="StackPanel_KeyUp">
<Button Name="ButtonA" Content="Button A"/>
<Button Name="ButtonB" Content="Button B"/>
<TextBlock Name="statusTextBlock"/>
</StackPanel>
В следующем примере показано, как реализовать обработчик событий KeyUp для соответствующего содержимого XAML в предыдущем примере.
void StackPanel_KeyUp(object sender, KeyRoutedEventArgs e)
{
statusTextBlock.Text = String.Format(
"The key {0} was pressed while focus was on {1}",
e.Key.ToString(), (e.OriginalSource as FrameworkElement).Name);
}
Обратите внимание на использование свойства OriginalSource в предыдущем обработчике. Здесь OriginalSource указывает на объект, вызвавший событие. Объект не может быть StackPanel, так как StackPanel не является элементом управления и не может иметь фокус. Только одна из двух кнопок в StackPanel , возможно, вызвала событие, но какой из них? Используйте OriginalSource для различения фактического исходного объекта события, если вы обрабатываете событие родительского объекта.
Свойство Handled в данных события
В зависимости от вашей стратегии обработки событий может потребоваться, чтобы только один обработчик событий реагировал на всплывающее событие. Например, если у вас есть определенный обработчик KeyUp , подключенный к одному из элементов управления Button , он будет иметь первую возможность обрабатывать это событие. В этом случае, возможно, вы не захотите, чтобы родительская панель тоже обрабатывала событие. Для этого сценария можно использовать свойство Handled в данных события.
Цель свойства Handled в классе данных перенаправленного события — сообщить о том, что еще один обработчик, зарегистрированный ранее в маршруте событий, уже действовал. Это влияет на поведение системы маршрутизируемых событий. Если в обработчике события установить для Handled значение true, маршрутизация этого события прекращается, и оно не отправляется вышестоящим родительским элементам.
AddHandler и уже обработанные события клавиатуры
Вы можете использовать специальный приём для подключения обработчиков, которые могут обрабатывать события, уже помеченные как обработанные. Этот прием использует метод AddHandler для регистрации обработчика вместо использования атрибутов XAML или специфического для языка синтаксиса добавления обработчиков, например += в C#.
Общее ограничение этого метода заключается в том, что API AddHandler принимает параметр типа RoutedEvent, определяющий перенаправленное событие в вопросе. Не все перенаправленные события предоставляют идентификатор RoutedEvent , и это внимание, таким образом, влияет на то, какие перенаправленные события по-прежнему можно обрабатывать в обработанном случае. События KeyDown и KeyUp имеют идентификаторы маршрутизируемых событий (KeyDownEvent и KeyUpEvent) у UIElement. Однако другие события, такие как TextBox.TextChanged , не имеют перенаправленных идентификаторов событий и поэтому не могут использоваться с методом AddHandler .
Переопределение событий и поведения клавиатуры
Вы можете переопределить ключевые события для определенных элементов управления (например , GridView), чтобы обеспечить согласованную навигацию фокуса для различных устройств ввода, включая клавиатуру и геймпад.
В следующем примере мы подклассируем элемент управления и переопределим поведение KeyDown, чтобы переместить фокус на содержимое GridView при нажатии любого клавиши со стрелкой.
public class CustomGridView : GridView
{
protected override void OnKeyDown(KeyRoutedEventArgs e)
{
// Override arrow key behaviors.
if (e.Key != Windows.System.VirtualKey.Left && e.Key !=
Windows.System.VirtualKey.Right && e.Key !=
Windows.System.VirtualKey.Down && e.Key !=
Windows.System.VirtualKey.Up)
base.OnKeyDown(e);
else
FocusManager.TryMoveFocus(FocusNavigationDirection.Down);
}
}
Замечание
Если GridView используется только для разметки, рассмотрите возможность использования других элементов, таких как ItemsControl с ItemsWrapGrid.
Командование
Небольшое количество элементов пользовательского интерфейса обеспечивает встроенную поддержку команд. Механизм команд использует в своей базовой реализации маршрутизируемые события, связанные с вводом. Он позволяет обрабатывать связанные входные данные пользовательского интерфейса, такие как определенное действие указателя или определенный ключ акселератора, вызывая один обработчик команд.
Если команда доступна для элемента пользовательского интерфейса, рассмотрите возможность использования интерфейсов API команд вместо каких-либо дискретных событий ввода. Дополнительные сведения см. в разделе ButtonBase.Command.
Вы также можете реализовать ICommand для инкапсулировать функции команд, которые вызываются из обычных обработчиков событий. Это позволяет использовать команду, даже если не доступно свойство Command .
Ввод текста и элементы управления
Некоторые элементы управления обрабатывают события клавиатуры по-своему. Например, TextBox — это элемент управления, предназначенный для записи, а затем визуально представлять текст, введенный с помощью клавиатуры. Он использует KeyUp и KeyDown в собственной логике для записи нажатий клавиш, а также вызывает собственное событие TextChanged , если текст фактически изменился.
Вы по-прежнему можете добавлять обработчики для KeyUp и KeyDown в текстовое поле или любой связанный элемент управления, предназначенный для обработки ввода текста. Однако в рамках своей предполагаемой структуры элемент управления может не реагировать на все ключевые значения, направленные на него с помощью ключевых событий. Поведение зависит от каждого элемента управления.
Например, ButtonBase (базовый класс для Button) обрабатывает KeyUp, чтобы проверить нажатие клавиши пробела или Enter. ButtonBase считает KeyUp эквивалентным нажатию левой кнопки мыши при вызове события Click. Эта обработка события выполняется, когда ButtonBase переопределяет виртуальный метод OnKeyUp. В своей реализации он устанавливает Handled в значение true. В результате любой родительский элемент кнопки, прослушивающий событие клавиатуры, в случае нажатия клавиши пробела не получит уже обработанное событие в своих обработчиках.
Другим примером является TextBox. Некоторые клавиши, такие как клавиши со стрелками, не считаются текстом в TextBox, а вместо этого считаются относящимися к поведению пользовательского интерфейса элемента управления. Текстовое поле помечает эти случаи событий как обрабатываемые.
Пользовательские элементы управления могут реализовывать собственное аналогичное поведение переопределения для событий клавиш, переопределяя OnKeyDown / OnKeyUp. Если ваш пользовательский элемент управления обрабатывает определённые клавиши быстрого доступа или имеет поведение, связанное с элементом управления или фокусом, аналогичное сценарию, описанному для TextBox, следует реализовать эту логику в собственных переопределениях OnKeyDown / OnKeyUp.
Сенсорная клавиатура
Элементы управления вводом текста обеспечивают автоматическую поддержку сенсорной клавиатуры. Когда пользователь переводит фокус ввода на текстовое поле с помощью касания, экранная клавиатура появляется автоматически. Если фокус ввода не находится в текстовом поле, сенсорная клавиатура скрывается.
При появлении сенсорной клавиатуры он автоматически перемещает пользовательский интерфейс, чтобы убедиться, что фокусный элемент остается видимым. Это может привести к тому, что другие важные элементы интерфейса сместятся за пределы экрана. Однако вы можете отключить поведение по умолчанию и внести собственные корректировки пользовательского интерфейса при появлении сенсорной клавиатуры. Дополнительные сведения см. в примере клавиатуры Touch.
Если вы создаете пользовательский элемент управления, требующий ввода текста, но не производный от стандартного элемента управления вводом текста, можно добавить поддержку сенсорной клавиатуры, реализуя правильные шаблоны элементов управления модель автоматизации пользовательского интерфейса. Дополнительные сведения см. в примере клавиатуры Touch.
Нажатие клавиш на сенсорной клавиатуре вызывает события KeyDown и KeyUp так же, как нажатие клавиши на аппаратных клавиатурах. Однако сенсорный клавиатура не будет вызывать входные события для клавиш CTRL+A, CTRL+Z, CTRL+X, CTRL+C и CTRL+V, которые зарезервированы для обработки текста в элементе управления входными данными.
Вы можете значительно ускорить и упростить ввод данных пользователями в вашем приложении, установив область ввода текстового элемента управления в соответствии с ожидаемым типом данных, которые пользователь должен ввести. Область ввода указывает, какой тип текстового ввода ожидается элементом управления, чтобы система могла предоставить специализированную раскладку сенсорной клавиатуры для данного типа ввода. Например, если текстовое поле используется только для ввода 4-значного PIN-кода, установите для свойства InputScope значение Number. Это позволяет системе отображать цифровой макет клавиатуры, что упрощает ввод ПИН-кода пользователем. Дополнительные сведения см. в разделе "Использование области ввода" для изменения сенсорной клавиатуры.
Связанные статьи
Разработчики
Дизайнеры
Samples
- пример сенсорной клавиатуры
- Базовый пример входных данных
- Пример ввода с низкой задержкой
- Пример визуальных элементов фокуса
Архивные примеры
Windows developer