一个优秀的Windows应用不仅要面向鼠标、触屏用户,同时还需要兼顾到键盘操作,特别是一些常见的快捷键,比如撤销(CTRL + Z),以提供全面的用户体验。

那么在UWP里如何定义键盘快捷键呢,以我的《描图》APP为例,我需要实现撤销的快捷键(CTRL + Z)。首先,我们需要定义快捷键的操作,是用户当前焦点在哪个控件上的,如果需要整个应用界面都监听键盘操作,那么这个UI控件就是XAML页面最外层的容器:GRID

所以,首先我们在Page下面的第一级Grid,也就是最外层容器上,定义2个事件:KeyDownKeyUp,如下:

<Grid Background="{ThemeResource TracingAcrylicBrush}" KeyDown="LayoutRoot_KeyDown" KeyUp="LayoutRoot_KeyUp">

接下来,因为我们想操作的快捷键(CTRL + Z)是个组合键,所以我们需要知道用户是否按同时按下了CTRL键和Z键,为此,我们要定义一个布尔变量用来标识CTRL是否已被按下的状态:

private bool _isCtrlKeyPressed;

然后定义事件处理函数:

private void LayoutRoot_KeyUp(object sender, KeyRoutedEventArgs e)

以及

private async void LayoutRoot_KeyDown(object sender, KeyRoutedEventArgs e)

用来判断用户按下的是哪个键的参数,就是KeyRoutedEventArgs e。按键是用Windows.System.VirtualKey这个枚举来表示的。所以要判断是否按下CTRL,只要判断e.Key == VirtualKey.Control。那么关于记录CTRL键状态的逻辑就是,按下CTRL的时候,给_isCtrlKeyPressed赋值为true,否则(松开按键)就是false:

private void LayoutRoot_KeyUp(object sender, KeyRoutedEventArgs e)
{
    if (e.Key == VirtualKey.Control) _isCtrlKeyPressed = false;
}

private async void LayoutRoot_KeyDown(object sender, KeyRoutedEventArgs e)
{
    if (e.Key == VirtualKey.Control) _isCtrlKeyPressed = true;
}

接下来就是判断用户是否按了Z键,也是在LayoutRoot_KeyDown事件处理函数里,判断CTRL是否已按下之后,接着判断e.Key是不是Z,就像这样:

private async void LayoutRoot_KeyDown(object sender, KeyRoutedEventArgs e)
{
    if (e.Key == VirtualKey.Control) _isCtrlKeyPressed = true;
    else if (_isCtrlKeyPressed)
    {
        switch (e.Key)
        {
            case VirtualKey.Z: ViewModel.CommandUndo.Execute(null); break;
        }
    }
}

现在你的应用界面就已经可以响应CTRL+Z组合键的操作了。

同理,如果你有别的和CTRL配合使用的快捷键,也可以放在swtich case里一起:

case VirtualKey.V: await PasteInkOrImageFromClipboard(); break;
case VirtualKey.Z: ViewModel.CommandUndo.Execute(null); break;
case VirtualKey.Y: ViewModel.CommandRedo.Execute(null); break;
case VirtualKey.S: ViewModel.CommandSaveCurrent.Execute(null); break;