教程:在 Windows 应用中支持墨迹

Surface Pen 主视觉图像。
Surface 触控笔 (可在 Microsoft 应用商店购买)。

本教程逐步介绍如何创建支持使用 Windows Ink 编写和绘图的基本 Windows 应用。 我们使用示例应用中的代码片段(可从 GitHub 下载)(请参阅 示例代码),以演示每个步骤中讨论的各种功能和关联的 Windows Ink API(请参阅 Windows Ink 平台的组件)。

我们专注于以下事项:

  • 添加基本墨迹支持
  • 添加墨水工具栏
  • 支持手写识别
  • 支持基本形状识别
  • 保存和加载墨水

有关如何实现这些功能的更多详细信息,请参阅 Windows 应用中的 笔互动和 Windows Ink

介绍

借助 Windows Ink,你可以为客户提供几乎所有可以想象的笔和纸体验的数字等效。从快速书写笔记和批注到白板演示,再到建筑和工程绘图,甚至是个人杰作。

先决条件

注释

虽然 Windows Ink 支持使用鼠标和触摸来进行绘制(在本教程步骤 3 中,我们演示了具体操作方法),但为了获得最佳的 Windows Ink 体验,我们建议你使用数字触控笔,以及一台支持该数字触控笔输入的显示设备的计算机。

示例代码

在本教程中,我们使用示例墨迹应用来演示所讨论的概念和功能。

windows-appsample-get-started-ink 示例,从 GitHub 下载此 Visual Studio 示例和源代码:

  1. 选择绿色 克隆或下载 按钮
    克隆存储库。
  2. 如果您有 GitHub 帐户,可以通过选择 在 Visual Studio 中打开 将仓库克隆到本地计算机。
  3. 如果没有 GitHub 帐户,或者只需要项目的本地副本,请选择 “下载 ZIP ”(必须定期查看以下载最新更新)

重要

示例中的大部分代码都会注释掉。当我们完成每个步骤时,系统会要求你取消注释代码的各个部分。 在 Visual Studio 中,只需突出显示代码行,然后按 CTRL-K,然后按 Ctrl-U。

Windows Ink 平台的组件

这些对象为 Windows 应用提供大量墨迹书写体验。

组件 DESCRIPTION
InkCanvas 一个 XAML UI 平台控件,默认情况下接收来自笔的所有输入,并将其显示为墨水笔迹或擦除笔迹。
InkPresenter 后台代码对象,与 InkCanvas 控件同时实例化(通过 InkCanvas.InkPresenter 属性公开)。 此对象提供 InkCanvas公开的所有默认墨迹功能,以及一套全面的 API 以支持额外的自定义和个性化。
墨迹工具栏 XAML UI 平台控件,其中包含可自定义且可扩展的按钮集合,这些按钮在关联的 InkCanvas 中激活与墨迹相关的功能。
IInkD2DRenderer
此处未介绍此功能,有关详细信息,请参阅 复杂墨迹示例
启用将墨迹笔划呈现到通用 Windows 应用的指定 Direct2D 设备上下文,而不是默认的 InkCanvas 控件。

步骤 1:运行示例

下载 RadialController 示例应用后,请验证它是否运行:

  1. 在 Visual Studio 中打开示例项目。

  2. 解决方案平台 下拉列表设置为非 Arm 的选项。

  3. 按 F5 编译、部署和运行。

    注释

    或者,可以选择“调试开始调试>”菜单项,或选择此处显示的“本地计算机运行”按钮。 Visual Studio 生成项目按钮。

应用窗口随即打开,启动画面显示几秒钟后,你将看到此初始屏幕。

空应用的屏幕截图。

好吧,我们现在有基本的 Windows 应用,我们将在整个本教程的其余部分使用。 在以下步骤中,我们将添加墨迹功能。

步骤 2:使用 InkCanvas 支持基本墨迹书写

也许你可能已经注意到,应用在初始表单中不会让你使用笔绘制任何内容(尽管你可以使用笔作为标准指针设备来与应用交互)。

我们来修复此步骤中的小缺点。

若要添加基本墨迹书写功能,只需将 InkCanvas 控件放在应用中的相应页面上即可。

注释

InkCanvas 默认的 高度宽度 属性为零,除非它是一个会自动调整子元素大小的元素的子元素。

在示例中:

  1. 打开MainPage.xaml.cs文件。
  2. 查找标记为此步骤标题的代码(“// 步骤 2:使用 InkCanvas 支持基本墨迹书写”)。
  3. 取消注释以下行。 (后续步骤中使用的功能需要这些引用)。
    using Windows.UI.Input.Inking;
    using Windows.UI.Input.Inking.Analysis;
    using Windows.UI.Xaml.Shapes;
    using Windows.Storage.Streams;
  1. 打开 MainPage.xaml 文件。
  2. 查找带有此步骤标题标记的代码(“<!-- 步骤 2:使用 InkCanvas 进行基本墨迹书写 -->”)。
  3. 取消注释以下行。
    <InkCanvas x:Name="inkCanvas" />

就是这样!

现在再次运行应用。 继续写字,写你的名字,或者(如果你拿着镜子或有非常好的记忆),绘制你的自我肖像。

本主题中展示的基本墨迹示例应用程序的屏幕截图。

步骤 3:支持使用触摸和鼠标墨迹书写

你会注意到,默认情况下,笔输入仅支持墨迹。 如果你尝试用手指、鼠标或触摸板书写或绘制,你会感到失望。

若要使皱眉倒置,需要添加第二行代码。 这一次,它位于声明 InkCanvas 的 XAML 文件的后台代码中。

在此步骤中,我们将介绍 InkPresenter 对象,该对象在 InkCanvas上提供对墨迹输入(标准和修改)的输入、处理和呈现的精细管理。

注释

标准墨迹输入(笔尖或橡皮擦尖端/按钮)未使用辅助硬件功能进行修改,例如笔杆按钮、鼠标右键或类似机制。

要启用鼠标和触摸墨迹书写,请将 InkPresenterInputDeviceTypes 属性设置为所需的 CoreInputDeviceTypes 值的组合。

在示例中:

  1. 打开MainPage.xaml.cs文件。
  2. 查找标记为此步骤标题的代码(“//步骤 3:支持触摸和鼠标墨迹书写”)。
  3. 取消注释以下行。
    inkCanvas.InkPresenter.InputDeviceTypes =
        Windows.UI.Core.CoreInputDeviceTypes.Mouse | 
        Windows.UI.Core.CoreInputDeviceTypes.Touch | 
        Windows.UI.Core.CoreInputDeviceTypes.Pen;

再次运行应用,你会发现所有手指画在计算机屏幕上的梦想都成真了!

注释

指定输入设备类型时,必须指示对每种特定输入类型(包括笔)的支持,因为设置此属性会替代默认 的 InkCanvas 设置。

步骤 4:添加墨迹工具栏

InkToolbar 是一个 UWP 平台控件,它提供可自定义且可扩展的按钮集合,用于激活与墨迹相关的功能。

默认情况下,InkToolbar 包含一组基本按钮,用户可以快速选择使用笔、铅笔、荧光笔或橡皮擦,并可以与辅助工具(尺子或量角器)搭配使用。 每个笔、铅笔和荧光笔按钮还提供用于选择墨迹颜色和笔划大小的浮出控件。

若要将默认 InkToolbar 添加到墨迹书写应用,只需将其放置在与 InkCanvas 相同的页面上,并关联这两个控件。

在示例中

  1. 打开 MainPage.xaml 文件。
  2. 查找带有此步骤标题的代码(“<!-- 步骤 4:添加墨迹工具栏 -->”)。
  3. 取消注释以下行。
    <InkToolbar x:Name="inkToolbar" 
                        VerticalAlignment="Top" 
                        Margin="10,0,10,0"
                        TargetInkCanvas="{x:Bind inkCanvas}">
    </InkToolbar>

注释

为了尽可能地保持 UI 和代码的整洁和简单,我们使用了基本的网格布局,并在网格行中将 InkToolbar 声明在 InkCanvas 之后。 如果在 InkCanvas之前声明它,那么会首先呈现 InkToolbar,位于画布下方,并且用户无法访问。

现在再次运行应用以查看 InkToolbar 并试用一些工具。

本主题中突出显示的示例应用“基础墨迹”的屏幕截图,其中包含默认的墨迹工具栏。

挑战:添加自定义按钮

下面是自定义 InkToolbar(从 Windows Ink 工作区中的绘图板)的示例。

墨迹工作区中草图板中的墨迹工具栏的屏幕截图。

有关自定义 InkToolbar的更多详细信息,请参阅 将 InkToolbar 添加到 Windows 应用墨迹书写应用

步骤 5:支持手写识别

现在你可以在应用中进行书写和绘图了,接下来让我们尝试对这些涂鸦做一些有用的事情。

在此步骤中,我们使用 Windows Ink 的手写识别功能来尝试破译你已写的内容。

注释

可以通过 笔和 Windows 墨迹 设置改进手写识别:

  1. 打开“开始”菜单,然后选择“设置”
  2. 从“设置”屏幕中选择 “设备>笔和 Windows 墨迹”。 “笔和 Windows Ink 设置”页的屏幕截图。
  3. 选择“我的手写习惯”以打开“手写个性化” 对话框。 “手写识别个性化”对话框的屏幕截图。

在示例中:

  1. 打开 MainPage.xaml 文件。
  2. 查找标记为此步骤标题的代码(“<--步骤 5:支持手写识别 --”>
  3. 取消注释以下行。
    <Button x:Name="recognizeText" 
            Content="Recognize text"  
            Grid.Row="0" Grid.Column="0"
            Margin="10,10,10,10"
            Click="recognizeText_ClickAsync"/>
    <TextBlock x:Name="recognitionResult" 
                Text="Recognition results: "
                VerticalAlignment="Center" 
                Grid.Row="0" Grid.Column="1"
                Margin="50,0,0,0" />
  1. 打开MainPage.xaml.cs文件。
  2. 查找标记为此步骤标题的代码(“步骤 5:支持手写识别”)。
  3. 取消注释以下行。
  • 这是此步骤所需的全局变量。
    InkAnalyzer analyzerText = new InkAnalyzer();
    IReadOnlyList<InkStroke> strokesText = null;
    InkAnalysisResult resultText = null;
    IReadOnlyList<IInkAnalysisNode> words = null;
  • 这是 识别文本 按钮的处理程序,我们在这里执行识别任务。
    private async void recognizeText_ClickAsync(object sender, RoutedEventArgs e)
    {
        strokesText = inkCanvas.InkPresenter.StrokeContainer.GetStrokes();
        // Ensure an ink stroke is present.
        if (strokesText.Count > 0)
        {
            analyzerText.AddDataForStrokes(strokesText);

            resultText = await analyzerText.AnalyzeAsync();

            if (resultText.Status == InkAnalysisStatus.Updated)
            {
                words = analyzerText.AnalysisRoot.FindNodes(InkAnalysisNodeKind.InkWord);
                foreach (var word in words)
                {
                    InkAnalysisInkWord concreteWord = (InkAnalysisInkWord)word;
                    foreach (string s in concreteWord.TextAlternates)
                    {
                        recognitionResult.Text += s;
                    }
                }
            }
            analyzerText.ClearDataForAllStrokes();
        }
    }
  1. 再次运行应用程序,编写内容,然后单击 “识别文本” 按钮。
  2. 识别结果显示在按钮旁边

挑战 1:国际认可

Windows Ink 支持对 Windows 支持的许多语言的文本识别。 每个语言包都包含一个手写识别引擎,可以随语言包一起安装。

通过查询已安装的手写识别引擎来定位特定语言。

有关国际手写识别的更多详细信息,请参阅 将 Windows 墨迹笔划识别为文本

挑战 2:动态识别

在本教程中,我们需要按下按钮来启动识别。 还可以使用基本计时函数执行动态识别。

有关动态识别的更多详细信息,请参阅 将 Windows 墨迹笔划识别为文本

步骤 6:识别形状

好吧,所以现在你可以将手写笔记转换为更清晰的东西。 但是,早晨流程图爱好者匿名聚会上的那些咖啡因驱动的摇摇晃晃的涂鸦呢?

使用墨迹分析,应用还可以识别一组核心形状,包括:

  • 菱形
  • 绘图
  • 椭圆
  • 等边三角形
  • 六角形
  • 等腰三角形
  • 平行四边形
  • 五角大楼
  • 四边形
  • 矩形
  • RightTriangle
  • 正方形
  • 梯形
  • 三角形

在此步骤中,我们使用 Windows Ink 的形状识别功能来尝试清理你的涂鸦。

对于此示例,我们不会尝试重绘墨迹笔划(尽管可能)。 我们在 InkCanvas 下添加一个标准画布,用于绘制从原始墨迹派生的等效椭圆或多边形对象。 然后删除相应的墨迹笔划。

在示例中:

  1. 打开 MainPage.xaml 文件
  2. 查找标记为此步骤标题的代码(“<--步骤 6: 识别形状 -->”)
  3. 取消注释此行。
   <Canvas x:Name="canvas" />

   And these lines.

    <Button Grid.Row="1" x:Name="recognizeShape" Click="recognizeShape_ClickAsync"
        Content="Recognize shape" 
        Margin="10,10,10,10" />
  1. 打开MainPage.xaml.cs文件
  2. 找到标有此步骤标题的代码(“// 第 6 步:识别形状”)
  3. 取消注释以下行:
    private async void recognizeShape_ClickAsync(object sender, RoutedEventArgs e)
    {
        ...
    }

    private void DrawEllipse(InkAnalysisInkDrawing shape)
    {
        ...
    }

    private void DrawPolygon(InkAnalysisInkDrawing shape)
    {
        ...
    }
  1. 运行应用,绘制一些形状,然后单击“ 识别形状 ”按钮

下面是数字餐巾纸中基本的流程图示例。

数字便签中的简易流程图的屏幕截图。

形状识别后,流程图相同。

用户选择“识别”形状后流程图的屏幕截图。

步骤 7:保存和加载墨迹

那么,你已经乱涂乱画了,对所看到的感到满意,但认为稍后可能会想修改一些东西? 可以将数字墨迹保存为墨迹序列化格式(ISF)文件,并在灵感来临时加载它们进行编辑。

ISF 文件是一个基本的 GIF 图像,其中包含描述墨迹笔划属性和行为的附加元数据。 未启用墨迹的应用可以忽略额外的元数据,但仍加载基本 GIF 图像(包括 alpha 通道背景透明度)。

注释

墨迹序列化格式(ISF)规范可以从 微软下载中心获取。

在此步骤中,我们需要将墨迹工具栏旁的“保存”按钮和“加载”按钮关联起来。

在示例中:

  1. 打开 MainPage.xaml 文件。
  2. 查找标记为此步骤标题的代码(“<--步骤 7:保存和加载墨迹 -->”)。
  3. 取消注释以下行。
    <Button x:Name="buttonSave" 
            Content="Save" 
            Click="buttonSave_ClickAsync"
            Width="100"
            Margin="5,0,0,0"/>
    <Button x:Name="buttonLoad" 
            Content="Load"  
            Click="buttonLoad_ClickAsync"
            Width="100"
            Margin="5,0,0,0"/>
  1. 打开MainPage.xaml.cs文件。
  2. 找到标有本步骤标题的代码(“// 第7步:保存并加载墨迹”)。
  3. 取消注释以下行。
    private async void buttonSave_ClickAsync(object sender, RoutedEventArgs e)
    {
        ...
    }

    private async void buttonLoad_ClickAsync(object sender, RoutedEventArgs e)
    {
        ...
    }
  1. 运行应用并绘制内容。
  2. 选择“ 保存 ”按钮并保存绘图。
  3. 擦除墨迹或重启应用。
  4. 选择“加载”按钮并打开刚保存的墨迹文件。

挑战:使用剪贴板复制和粘贴墨迹笔划

Windows 墨迹还支持从剪贴板复制和粘贴墨迹笔划。

有关将剪贴板与墨迹一起使用的更多详细信息,请参阅 存储和检索 Windows 墨迹笔划数据

概要

恭喜,你已完成 输入:在 Windows 应用中支持墨迹 教程! 我们介绍了在 Windows 应用中支持墨迹所需的基本代码,以及如何提供 Windows Ink 平台支持的一些更丰富的用户体验。

示例