Практическое руководство. Анализ данных рукописного ввода с помощью подсказок анализа
System.Windows.Ink.AnalysisHintNode предоставляет подсказку для System.Windows.Ink.InkAnalyzer к которому он присоединен. Указание применяется к области, заданной System.Windows.Ink.ContextNode.Location%2A свойство System.Windows.Ink.AnalysisHintNode и предоставляет дополнительный контекст к анализатору рукописного ввода повышения точности распознавания. System.Windows.Ink.InkAnalyzer применяет эти сведения при анализ рукописного ввода полученных в пределах области подсказок.
Пример
Следующий пример — это приложение, в которой используется несколько System.Windows.Ink.AnalysisHintNode объектов в форме, которая принимает входные данные рукописного ввода. Приложение использует System.Windows.Ink.AnalysisHintNode.Factoid%2A свойство, чтобы предоставить сведения о контексте для каждой записи в форме. Приложение использует фоновый анализ для анализа рукописного ввода и очищает формы все рукописные данные через пять секунд после пользователь останавливает добавление рукописного ввода.
<Window x:Class="FormAnalyzer"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="FormAnalyzer"
SizeToContent="WidthAndHeight"
>
<StackPanel Orientation="Vertical">
<InkCanvas Name="xaml_writingCanvas" Height="500" Width="840"
StrokeCollected="RestartAnalysis" >
<Grid>
<Grid.Resources>
<Style TargetType="{x:Type Label}">
<Setter Property="FontSize" Value="20"/>
<Setter Property="FontFamily" Value="Arial"/>
</Style>
<Style TargetType="{x:Type TextBlock}">
<Setter Property="FontSize" Value="18"/>
<Setter Property="VerticalAlignment" Value="Center"/>
</Style>
</Grid.Resources>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="100"></ColumnDefinition>
<ColumnDefinition Width="160"></ColumnDefinition>
<ColumnDefinition Width="160"></ColumnDefinition>
<ColumnDefinition Width="100"></ColumnDefinition>
<ColumnDefinition Width="160"></ColumnDefinition>
<ColumnDefinition Width="160"></ColumnDefinition>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="100"></RowDefinition>
<RowDefinition Height="100"></RowDefinition>
<RowDefinition Height="100"></RowDefinition>
<RowDefinition Height="100"></RowDefinition>
<RowDefinition Height="100"></RowDefinition>
</Grid.RowDefinitions>
<Label Grid.Row="0" Grid.Column="0">Title</Label>
<Label Grid.Row="1" Grid.Column="0">Director</Label>
<Label Grid.Row="2" Grid.Column="0">Starring</Label>
<Label Grid.Row="3" Grid.Column="0">Rating</Label>
<Label Grid.Row="3" Grid.Column="3">Year</Label>
<Label Grid.Row="4" Grid.Column="0">Genre</Label>
<TextBlock Name="xaml_blockTitle"
Grid.Row="0" Grid.Column="1"
Grid.ColumnSpan="5"/>
<TextBlock Name="xaml_blockDirector"
Grid.Row="1" Grid.Column="1"
Grid.ColumnSpan="5"/>
<TextBlock Name="xaml_blockStarring"
Grid.Row="2" Grid.Column="1"
Grid.ColumnSpan="5"/>
<TextBlock Name="xaml_blockRating"
Grid.Row="3" Grid.Column="1"
Grid.ColumnSpan="2"/>
<TextBlock Name="xaml_blockYear"
Grid.Row="3" Grid.Column="4"
Grid.ColumnSpan="2"/>
<TextBlock Name="xaml_blockGenre"
Grid.Row="4" Grid.Column="1"
Grid.ColumnSpan="5"/>
<Line Grid.Row="0" Grid.Column="0" Grid.ColumnSpan="6"
StrokeThickness="2" Stroke="Black"
X1="0" Y1="100" X2="840" Y2="100" />
<Line Grid.Row="1" Grid.Column="0" Grid.ColumnSpan="6"
StrokeThickness="2" Stroke="Black"
X1="0" Y1="100" X2="840" Y2="100" />
<Line Grid.Row="2" Grid.Column="0" Grid.ColumnSpan="6"
StrokeThickness="2" Stroke="Black"
X1="0" Y1="100" X2="840" Y2="100" />
<Line Grid.Row="3" Grid.Column="0" Grid.ColumnSpan="6"
StrokeThickness="2" Stroke="Black"
X1="0" Y1="100" X2="840" Y2="100" />
<Line Grid.Row="3" Grid.Column="0" Grid.ColumnSpan="6"
StrokeThickness="2" Stroke="Black"
X1="420" Y1="0" X2="420" Y2="100" />
</Grid>
</InkCanvas>
</StackPanel>
</Window>
using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Ink;
using System.Windows.Threading;
public partial class FormAnalyzer : Window
{
private InkAnalyzer analyzer;
private AnalysisHintNode hintNodeTitle;
private AnalysisHintNode hintNodeDirector;
private AnalysisHintNode hintNodeStarring;
private AnalysisHintNode hintNodeRating;
private AnalysisHintNode hintNodeYear;
private AnalysisHintNode hintNodeGenre;
// Timer that raises an event to
// clear the InkCanvas.
private DispatcherTimer strokeRemovalTimer;
private const int CLEAR_STROKES_DELAY = 5;
public FormAnalyzer()
{
InitializeComponent();
}
protected override void OnContentRendered(EventArgs e)
{
base.OnContentRendered(e);
// Initialize the Analyzer.
analyzer = new InkAnalyzer();
analyzer.ResultsUpdated +=
new ResultsUpdatedEventHandler(analyzer_ResultsUpdated);
// Add analysis hints for each form area.
// Use the absolute Width and Height of the Grid's
// RowDefinition and ColumnDefinition properties defined in XAML,
// to calculate the bounds of the AnalysisHintNode objects.
hintNodeTitle = analyzer.CreateAnalysisHint(
new Rect(100, 0, 740, 100));
hintNodeDirector = analyzer.CreateAnalysisHint(
new Rect(100, 100, 740, 100));
hintNodeStarring = analyzer.CreateAnalysisHint(
new Rect(100, 200, 740, 100));
hintNodeRating = analyzer.CreateAnalysisHint(
new Rect(100, 300, 320, 100));
hintNodeYear = analyzer.CreateAnalysisHint(
new Rect(520, 300, 320, 100));
hintNodeGenre = analyzer.CreateAnalysisHint(
new Rect(100, 400, 740, 100));
//Set the factoids on the hints.
hintNodeTitle.Factoid = "(!IS_DEFAULT)";
hintNodeDirector.Factoid = "(!IS_PERSONALNAME_FULLNAME)";
hintNodeStarring.Factoid = "(!IS_PERSONALNAME_FULLNAME)";
hintNodeRating.Factoid = "(!IS_DEFAULT)";
hintNodeYear.Factoid = "(!IS_DATE_YEAR)";
hintNodeGenre.Factoid = "(!IS_DEFAULT)";
}
/// <summary>
/// InkCanvas.StrokeCollected event handler. Begins
/// ink analysis and starts the timer to clear the strokes.
/// If five seconds pass without a Stroke being added,
/// the strokes on the InkCanvas will be cleared.
/// </summary>
/// <par am name="sender">InkCanvas that raises the
/// StrokeCollected event.</param>
/// <param name="args">Contains the event data.</param>
private void RestartAnalysis(object sender,
InkCanvasStrokeCollectedEventArgs args)
{
// If strokeRemovalTimer is enabled, stop it.
if (strokeRemovalTimer != null && strokeRemovalTimer.IsEnabled)
{
strokeRemovalTimer.Stop();
}
// Restart the timer to clear the strokes in five seconds
strokeRemovalTimer = new DispatcherTimer(
TimeSpan.FromSeconds(CLEAR_STROKES_DELAY),
DispatcherPriority.Normal,
ClearCanvas,
Dispatcher.CurrentDispatcher);
// Add the new stroke to the InkAnalyzer and
// begin background analysis.
analyzer.AddStroke(args.Stroke);
analyzer.BackgroundAnalyze();
}
/// <summary>
/// Analyzer.ResultsUpdated event handler.
/// </summary>
/// <param name="sender">InkAnalyzer that raises the
/// event.</param>
/// <param name="e">Event data</param>
/// <remarks>This method checks each AnalysisHint for
/// analyzed ink and then populated the TextBlock that
/// corresponds to the area on the form.</remarks>
void analyzer_ResultsUpdated(object sender, ResultsUpdatedEventArgs e)
{
string recoText;
recoText = hintNodeTitle.GetRecognizedString();
if (recoText != "") xaml_blockTitle.Text = recoText;
recoText = hintNodeDirector.GetRecognizedString();
if (recoText != "") xaml_blockDirector.Text = recoText;
recoText = hintNodeStarring.GetRecognizedString();
if (recoText != "") xaml_blockStarring.Text = recoText;
recoText = hintNodeRating.GetRecognizedString();
if (recoText != "") xaml_blockRating.Text = recoText;
recoText = hintNodeYear.GetRecognizedString();
if (recoText != "") xaml_blockYear.Text = recoText;
recoText = hintNodeGenre.GetRecognizedString();
if (recoText != "") xaml_blockGenre.Text = recoText;
}
//Clear the canvas, but leave the current strokes in the analyzer.
private void ClearCanvas(object sender, EventArgs args)
{
strokeRemovalTimer.Stop();
xaml_writingCanvas.Strokes.Clear();
}
}